HarmonyOS 鸿蒙Next Stage模型下从UIAbility向UI传参遇到的问题

HarmonyOS 鸿蒙Next Stage模型下从UIAbility向UI传参遇到的问题

stage模型下,

UIAbility页面

import UIAbility from '@ohos.app.ability.UIAbility';
let storageTest:LocalStorage= new LocalStorage({'got':[]})
export default class EntryAbility extends UIAbility {
    fetchData() {
        // promise
        let promise=balabala
        promise.then(() => {
            let tmp=[2,3]
            return tmp
        }).then(data => {
            let link=storageTest.link('got')
            link.set(data)
            console.info("来晚了"+JSON.stringify(data))
        }
    }
    onCreate(want, launch) {
        // 获取eventHub
        let eventhub = this.context.eventHub;
        // 执行订阅操作
        eventhub.on('event1', this.fetchData);
    }
}

UI页面

import common from '@ohos.app.ability.common';
@Component
struct Index {
    private context = getContext(this) as common.UIAbilityContext;
    @LocalStorageLink('got') 
    dataGot:[]=[];
    @State 
    show:string="button"
    
    eventHubFunc() {
        // 不带参数触发自定义“event1”事件
        this.context.eventHub.emit('event1');
    }

    build{
        Column(){
            Button(this.show).onClick(() => {
                this.EventHubFunc()
                this.show=JSON.stringify(this.dataGot)
                console.info('看到了'+this.dataGot)
            })
        }
    }
}

第一次点击的时候,info:

看到了[]

来晚了[2,3]

第二次点击的时候,info:

看到了[2,3]

来晚了[2,3]

也就是说,要点击两次按钮UI页面才能获得data[2,3]。这种情况只在含有promise异步回调时出现,

如果不是异步,只要点击一次就可以获得data[2,3]。

请问这是什么地方出了问题,怎么解决?

或者stage模型下,还有没有更好的方法从UIAbility向UI传参


更多关于HarmonyOS 鸿蒙Next Stage模型下从UIAbility向UI传参遇到的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

你这个Log就很明显了,第一次点击的时候先触发了点击操作,再出发的fetchData方法,所以点击操作中拿到的数据就是一个空数组,第二次点击的时候由于第一次点击的时候触发了fetchData方法,所以此时点击操作中是能拿到第一次点击时存储的操作。造成这个的问题的原因是promise是一个异步操作,异步操作就是可以先挂起执行别的代码。

参考文档:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/async-concurrency-overview-0000001632690002-V3?catalogVersion=V3

更多关于HarmonyOS 鸿蒙Next Stage模型下从UIAbility向UI传参遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


问题所在知道了,还是不会改,fetchData()改完如以上,结果还是两次点击才行

目的是要UI拿到data,您能指点下吗?

野生,这里过不去。。。

APPStoage,好像用这个挺好的,

import relationalStore from '@ohos.data.relationalStore';
const CREATE_TABLE_STAR = "CREATE TABLE IF NOT EXISTS new (" +
"id TEXT PRIMARY KEY," +
"Name TEXT)"
const STORE_CONFIG = {
  name: "WindRise.db",
  securityLevel: relationalStore.SecurityLevel.S1
}
var store
class Input{
  id:string
  Name:string
  constructor(option: {
    id: string
    Name: string
  }) {
    this.id=option.id
    this.Name=option.Name
  }
}
let StarInputBeans: Array<Input> = [
  {
    "id": "140105",
    "Name": "小明"
  },
  {
    "id": "140103",
    "Name": "小红"
  }]
let storageTest:LocalStorage= new LocalStorage({
'got':[2,3]})
export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
    globalThis.context = this.context
    this.InitDb()
    //eventhub
    let eventhub = this.context.eventHub;
    eventhub.on('event',this.queryDb)
  }
  InitDb() {
    let context = this.context
    let promise = relationalStore.getRdbStore(context, STORE_CONFIG);
    promise.then(async (rdbStore) => {
      store = rdbStore;
      console.info(`Get RdbStore successfully.`);
      store.executeSql(CREATE_TABLE_STAR)
      console.info(`Create new table done or Exist.`);
      for (var i = 0;i < StarInputBeans.length; i++) {
        let valueBucket = StarInputBeans[i]
        console.info(JSON.stringify(valueBucket))
        store.insert("new", valueBucket, function (err, rowId) {
          if (err) {
            console.error(`Insert is failed, code is ${err.code},message is ${err.message}`);
            return;
          }
          console.info(`Insert star is successful, rowId = ${rowId}`);
        })
      }
    }).catch((err) => {
      console.error(`Get RdbStore failed, code is ${err.code},message is ${err.message}`);
    })
  }
  queryDb(id: string) {
    let context = globalThis.getContext()
    let promise = relationalStore.getRdbStore(context, STORE_CONFIG);
    promise.then(async (rdbStore) => {
      store = rdbStore;
      let predicates_star = new relationalStore.RdbPredicates("new")
      predicates_star.equalTo("id", id)
      let promise = store.query(predicates_star, []);
      promise.then((resultSet) => {
        let result = []
        for (var i = 0;i < resultSet.rowCount; i++) {
          resultSet.goToRow(i);
          let res_item = {
            res_id: resultSet.getString(resultSet.getColumnIndex('id')),
            res_title: resultSet.getString(resultSet.getColumnIndex('Name'))
          }
          result.push(res_item)
        }
        let link = storageTest.link('got')
        link.set(result)
        console.info("没赶上" + JSON.stringify(result))
      }).catch((err) => {
        console.error(`Query failed, code is ${err.code},message is ${err.message}`);
      })
    })
  }
onWindowStageCreate(windowStage: window.WindowStage) {
  windowStage.loadContent('pages/Index', storageTest);
}

let storage = LocalStorage.GetShared()
@Entry(storage)
@Component
struct Index {
  @State message: string = 'Hello World'
  @LocalStorageLink('got') dataGot:[]=[]
  private context=getContext()
  eventHubFunc1(id:string){
    this.context.eventHub.emit('event',id)
  } 
 getData(){
  setTimeout(() =>{
    this.message=JSON.stringify(this.dataGot)
    console.info('来早了'+JSON.stringify(this.dataGot))
  }, 10);
 }
 build() {
  Row() {
    Column() {
      Button(this.message)
        .onClick(()=>{
          this.eventHubFunc1("140105")
          this.getData()
        })
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
      Button(this.message)
        .onClick(() =>{
          this.eventHubFunc1("140103")
          setTimeout(() => {
            this.message = JSON.stringify(this.dataGot)
            console.info('来早了' + JSON.stringify(this.dataGot))
          },10)
        })
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
  }
  .height('100%')
 }
}

以上给遇到同样问题的伙伴提供参考。

最后是在UI页面使用定时器解决的,如果有更好的办法,还请赐教。

如果只能这么解决,那官方是不是要考虑改进一下。

async fetchData(){
  let rdb = await relationshipStore.getRdbStore(context, STORE_CONFIG)
  const res = await new Promise(resolve => {
    rdb.query(predicates, [], () => {
      let data = [2, 3]
      resolve(data)
    })
  })
  let link = storageTest.link('got')
  link.set(res)
  console.info("2.0来晚了" + JSON.stringify(res))
}

在HarmonyOS中,UIAbility与UI之间的数据传递通常通过IntentAbilityContext实现。在Next Stage模型下,UIAbility向UI传参时,常见问题包括参数未正确传递或UI未正确接收。以下是可能的原因和解决方法:

  1. 参数未正确设置:在启动UI时,确保通过IntentAbilityContext正确设置参数。例如,使用Intent.setParam()方法传递参数。

  2. UI未正确接收参数:在UI的onStart()onNewIntent()方法中,确保通过Intent.getParam()方法获取传递的参数。

  3. 参数类型不匹配:确保传递的参数类型与UI中接收的参数类型一致。例如,传递的字符串参数应使用String类型接收。

  4. 生命周期问题:确保在UI的生命周期方法中正确获取参数。例如,在onStart()中获取参数,而不是在onCreate()中,因为onCreate()可能在某些情况下不会调用。

  5. Next Stage模型差异:Next Stage模型与之前的模型有所不同,确保了解并适应新的API和生命周期管理方式。

通过以上方法,可以解决大部分UIAbility向UI传参的问题。

回到顶部