HarmonyOS 鸿蒙Next数据更新,UI不刷新问题

发布于 1周前 作者 nodeper 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next数据更新,UI不刷新问题

class UnReadMsgItem{
  src: string;
  num: number;

  constructor(src: string, num: number) {
    this.src = src;
    this.num = num;
  }
}

export class UnReadMsgInfo {
  private static unReadMsgInfos: Array<UnReadMsgItem> = []

  constructor() {}

  static getUnReadMsgInfos():Array<UnReadMsgItem>{
    return UnReadMsgInfo.unReadMsgInfos;
  }

  static addUnReadMsgInfos(src: string, num: number){
    UnReadMsgInfo.unReadMsgInfos.push(new UnReadMsgItem(src, num));
  }
}

@Entry
@Component
struct StatusBarPage {
  private context = getContext(this) as common.UIAbilityContext;
   @State unReadMsgInfos : Array<UnReadMsgItem> = UnReadMsgInfo.getUnReadMsgInfos();

  build() {
    List({ space: 10}){
      ForEach(this.unReadMsgInfos, (item: UnReadMsgItem) => {
        ListItem() {
          Row() {
            Text(item.src).fontSize(20)
            Text(item.num.toString()).fontSize(20)
          }
          .width('100%')
          .justifyContent(FlexAlign.Center)
        }.onClick(()=>{
          let wantInfo: Want = {
            bundleName: 'com.example.hosapi12',
            moduleName: 'entry',
            abilityName: 'EntryAbility',
          };
          this.context.startAbility(wantInfo).then(() => {
            JsLogger.info("startAbility success");
          }).catch((error: BusinessError) => {
            JsLogger.error("startAbility failed:error, %{public}s", JSON.stringify(error));
          });
          JsDataStore.getQtNativeModule("QtOhExtras").handleMsgResult(item.src);
          StatusBarHandle.statusBarIconFlickerHandle(false);
        })
      }, (item: UnReadMsgItem) => JSON.stringify(item))
    }.width('100%')
    .alignListItem(ListItemAlign.Center)
    .scrollBar(BarState.Auto)
  }
}

如上代码,再其他ets文件地方调用addUnReadMsgInfos函数更新unReadMsgInfos,UI不能刷新。该如何修复呢?

6 回复
unReadMsgInfos 类型变为 ObservedArray<UnReadMsgItem>

ObservedArray.ets

/**
 * Wraps an array as an observed object
 */
[@Observed](/user/Observed)
export class ObservedArray<T> extends Array<T> {
  constructor(args?: T[]) {
    if (args instanceof Array) {
      super(...args);
    } else {
      super();
    }
  }
}
 

完整测试代码(新增了按钮点击后列表增加一条记录):

import { common } from "@kit.AbilityKit";
import { ObservedArray } from "../common/ObservedArray";

class UnReadMsgItem { src: string; num: number;

constructor(src: string, num: number) { this.src = src; this.num = num; } }

export class UnReadMsgInfo { private static unReadMsgInfos: ObservedArray<UnReadMsgItem> = new ObservedArray()

constructor() { }

static getUnReadMsgInfos(): Array<UnReadMsgItem> { return UnReadMsgInfo.unReadMsgInfos; }

static addUnReadMsgInfos(src: string, num: number) { UnReadMsgInfo.unReadMsgInfos.push(new UnReadMsgItem(src, num)); } }

@Component struct StatusBarPage { private context = getContext(this) as common.UIAbilityContext; @State unReadMsgInfos: Array<UnReadMsgItem> = UnReadMsgInfo.getUnReadMsgInfos();

build() { Column() { Button(‘add msg’).onClick(() => { const num = Math.floor(Math.random() * 1000) UnReadMsgInfo.addUnReadMsgInfos(‘src’, num) console.log(StatusBarPage list: ${UnReadMsgInfo.getUnReadMsgInfos().length}) })

    List({ space: <span class="hljs-number">10</span> }) {
      ForEach(<span class="hljs-keyword">this</span>.unReadMsgInfos, (item: UnReadMsgItem) =&gt; {
        ListItem() {
          Row() {
            Text(item.src).fontSize(<span class="hljs-number">20</span>)
            Text(item.num.toString()).fontSize(<span class="hljs-number">20</span>)
          }
          .width(<span class="hljs-string">'100%'</span>)
          .justifyContent(FlexAlign.Center)
        }.onClick(() =&gt; {
          console.log(`StatusBarPage click`)
        })
      }, (item: UnReadMsgItem) =&gt; <span class="hljs-built_in">JSON</span>.stringify(item))
    }.width(<span class="hljs-string">'100%'</span>)
    .alignListItem(ListItemAlign.Center)
    .scrollBar(BarState.Auto)
  }

} }

你好,感谢你的回复,我的使用场景与你的例子有些差异,我是在其他.ets文件中,调用addUnReadMsgInfos新增数据的,这样好像无法更新UI。代码如下:

import { UnReadMsgInfo }from ‘…/…/pages/StatusBarPage’; import StatusBarHandle from ‘…/…/statusbarhandle/StatusBarHandle’

export class JsMsgNotice { constructor() {}

msgNotification(src: string, num: number): boolean { UnReadMsgInfo.addUnReadMsgInfos(src, num); StatusBarHandle.statusBarIconFlickerHandle(true); return true; } }

在其他文件调用addUnReadMsgInfos也一样的, UnReadMsgInfo 类是单例的, 全局只有一个(因为你用static).

  1. 验证是否因为不在同一个文件造成的: 你可以试一下你之前代码, 在同一个ets文件中, 你调用增加addUnReadMsgInfos是否List 就会刷新?

ps: 通过ObservedArray代码改造后. 应该就可以了~

同一个文件是可以的。目前是在entryAbility中调用addUnReadMsgInfos更新数据,再StatusBarViewExtensionAbility中想同步更新UI,目前看这两个好像是不同进程的。

针对HarmonyOS 鸿蒙Next数据更新而UI不刷新的问题,这通常是因为@State只是监听数组的地址值,当数组内部的对象数据发生变化时,如果数组的地址值未改变,则UI不会重新渲染。

要解决这个问题,可以采取以下两种方法:

  1. 使用临时数组:先复制一个临时数组,修改临时数组中的数据,然后将临时数组重新赋值给原数组。这样由于地址值改变,UI会重新渲染。
  2. 利用map方法:直接修改原数组中的数据后,使用map方法遍历数组并返回一个新数组。虽然数组内容未变,但由于返回的是新数组,其地址值已改变,因此UI也会重新渲染。

以上两种方法均能有效解决HarmonyOS 鸿蒙Next中数据更新而UI不刷新的问题。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部