HarmonyOS鸿蒙Next中请问一下各位大佬@ObservedV2 + @Trace在V1页面上混合使用时,为什么UI没有自动刷新页面又没报错?

HarmonyOS鸿蒙Next中请问一下各位大佬@ObservedV2 + @Trace在V1页面上混合使用时,为什么UI没有自动刷新页面又没报错?

@ObservedV2+@Trace观察的2个类代码如下:

/**
 * 朋友圈用户数据
 */
[@ObservedV2](/user/ObservedV2)
export class FriendMoment {
  [@Trace](/user/Trace) id: string; // 唯一id
  [@Trace](/user/Trace) userName: string; // 用户名
  [@Trace](/user/Trace) avatar: ResourceStr; // 头像
  [@Trace](/user/Trace) text: string; // 文字
  [@Trace](/user/Trace) image?: ResourceStr; // 发布动态图片
  [@Trace](/user/Trace) video?: ResourceStr; // 发布动态视频

  constructor(id: string, userName: string, avatar: ResourceStr, text: string, image?: ResourceStr,
    video?: ResourceStr) {
    this.id = id;
    this.userName = userName;
    this.avatar = avatar;
    this.text = text;
    if (image !== undefined) {
      this.image = image;
    }
    ;
    if (video !== undefined) {
      this.video = video;
    }
  }
}

[@ObservedV2](/user/ObservedV2)
export class CommentData extends BasicDataSource<FriendMoment> {
  // 懒加载数据
  [@Trace](/user/Trace) private comments: Array<FriendMoment> = [];

  // TODO:知识点:获取懒加载数据源的数据长度
  totalCount(): number {
    return this.comments.length;
  }

  // 获取指定数据项
  getData(index: number): FriendMoment {
    return this.comments[index];
  }

  // TODO:知识点:存储数据到懒加载数据源中
  pushData(data: FriendMoment): void {
    this.comments.push(data);
    // 在数组头部添加数据
    this.notifyDataAdd(this.comments.length - 1);
  }

  addDataFirst(data: FriendMoment): void {
    this.comments.unshift(data);
    // 在数组头部添加数据
    this.notifyDataAdd(0);
  }
}
// 从云数据库加载数据
export async function LoadUserPostData(): Promise<CommentData> {
  let commentList: CommentData = new CommentData();

  let result = await DBUtil.queryAllPost()
  result.forEach(element => {
    if(element.id != undefined && element.nickName != undefined && element.avatar != undefined && element.text != undefined && element.postImage){
      let avatarBuf = buffer.from(element.avatar);
      let avatarBase64Str = avatarBuf.toString('base64')
      let postPhotoBuf = buffer.from(element.avatar);
      let postPhotoBase64Str = postPhotoBuf.toString('base64')
      commentList.pushData(new FriendMoment(element.id.toString(), element.nickName, avatarBase64Str, element.text,
        postPhotoBase64Str));
    }
  });
  return commentList;
}

页面完整代码如下,断点查看能从云数据库加载并返回commentList的最新数据,就是没有响应刷新UI。

import {HMRouter, HMRouterMgr} from "@hadss/hmrouter"
import DBUtil from '../util/DBUtil'
import {UserPost} from '../viewmodel/UserPost'
import { buffer } from '@kit.ArkTS';
import { promptAction, ToolBar, ToolBarOptions, ItemState } from '@kit.ArkUI';
import { FriendMoment, CommentData } from '../viewmodel/BasicDataSource';
import { OneMoment } from '../Components/OneMoment';
import Constants from '../common/Constants';
import { mockData, LoadUserPostData } from '../viewmodel/mockdata';
import { CommentInputDialog } from '../Components/CommentInputDialog';

const typeVideo: string = 'video';
const typeText: string = 'text';
const typeImage: string = 'image';

/**
 * 功能描述: 本示例主要介绍使用@ohos.file.photoAccessHelper实现访问系统相册获取媒体资源的多媒体发布场景
 *
 * 推荐场景: 需要调用系统图库的场景,如:上传图库图片、发布朋友圈等
 *
 * 核心组件:
 * 1. CommentInputDialog
 *
 * 实现步骤:
 * 1.使用LazyForEach+cacheCount+@Reusable实现懒加载列表。
 * 2.创建ListScroller对象,将ListScroller对象绑定到List组件内。
 * 3.在需要记录当前位置时通过currentOffset方法存储当前偏移量historyOffset,在需要跳转时用scrollTo方法跳转。
 */

@HMRouter({
  pageUrl: 'SharePosts',
})
@Entry
@Component
export struct SharePosts {
  @StorageLink('hasLogin') hasLogin: boolean = false
  @StorageLink('uid') uid: string = ''
  @State result?: UserPost[] = []
  @State imageBase64:string = ''
  private cachedCountNumber: number = 3; // 懒加载缓存数
  private controller1: TabsController = new TabsController()
  listScroller: ListScroller = new ListScroller(); // scroller控制器
  commentList: CommentData = new CommentData(); // 评论列表
  @State textInComment: string = ""; // 评论中的文字
  @State imageInComment: string = ''; // 评论中的图片列表
  @State videoInComment: string = '' // 评论中的视频列表
  @State dialogType: string = typeText; // 弹窗类型
  private scroller: ListScroller = new ListScroller();
  // 评论输入弹窗
  dialogController: CustomDialogController | null = new CustomDialogController({
    builder: CommentInputDialog({
      textInComment: $textInComment,
      imagesInComment: $imageInComment,
      videoInComment: $videoInComment,
      dialogType: $dialogType,
      publish: () => this.publishComment()
    }),
    autoCancel: true,
    alignment: DialogAlignment.Bottom,
    customStyle: true,
    offset: {
      dx: $r('app.integer.image_comment_dialog_offset_x'),
      dy: $r('app.integer.image_comment_dialog_offset_y')
    }
  });

  async aboutToAppear(){
    // // 加载初始数据
    //this.commentList = mockData();

    // 加载初始数据
     this.commentList = await LoadUserPostData();
  }

  getCurrentDate(): string {
    const date: Date = new Date();
    return `${date.getFullYear()}-${date.getMonth()}-${date.getDay()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
  }

  publishComment(): void {
    // 发布图片,须有选择图片
    if (this.dialogType == typeImage) {
      if (this.imageInComment !== undefined && this.imageInComment !== '') {
        const comment: FriendMoment =
          new FriendMoment(this.getCurrentDate(), "我的", $r("app.media.publish_multimedia_updates_photo0"),
            this.textInComment, this.imageInComment);
        this.commentList.addDataFirst(comment);
      } else {
        promptAction.showToast({
          message: $r('app.string.publish_multimedia_updates_input_image'),
        });
      }
    } else if (this.dialogType == typeVideo) {
      // 发布视频,须有视频
      if (this.videoInComment !== undefined && this.videoInComment !== '') {
        const comment: FriendMoment =
          new FriendMoment(this.getCurrentDate(), "我的", $r("app.media.publish_multimedia_updates_photo0"),
            this.textInComment, '', this.videoInComment);
        this.commentList.addDataFirst(comment);
      } else {
        promptAction.showToast({
          message: $r('app.string.publish_multimedia_updates_input_video'),
        });
      }
    } else if (this.dialogType == typeText) {
      if (this.textInComment) {
        const comment: FriendMoment =
          new FriendMoment(this.getCurrentDate(), "我的", $r("app.media.publish_multimedia_updates_photo0"),
            this.textInComment);
        this.commentList.addDataFirst(comment);
      } else {
        promptAction.showToast({
          message: $r('app.string.publish_multimedia_updates_input_comment'),
        });
      }
    }

    this.scroller.scrollToIndex(0, true, ScrollAlign.START);
  }

  aboutToDisappear() {
    // 将dialogController置空
    this.dialogController = null;
  }

  @Builder
  MyMenu() {
    Menu() {
      MenuItem({
        startIcon: $r("sys.media.ohos_ic_public_text"),
        content: $r('app.string.publish_multimedia_updates_post')
      })
        .onClick(() => {
          this.dialogType = typeText
          if (this.dialogController !== null) {
            // 打开评论输入弹窗
            this.dialogController.open();
          }
        })
        .id('Post')
      MenuItem({
        startIcon: $r("sys.media.save_button_picture"),
        content: $r('app.string.publish_multimedia_updates_photo')
      })
        .onClick(() => {
          this.dialogType = typeImage
          if (this.dialogController !== null) {
            // 打开评论输入弹窗
            this.dialogController.open();
          }
        })
        .id('Photo')
      MenuItem({
        startIcon: $r("sys.media.ohos_ic_public_video"),
        content: $r('app.string.publish_multimedia_updates_video')
      })
        .onClick(() => {
          this.dialogType = typeVideo
          if (this.dialogController !== null) {
            // 打开评论输入弹窗
            this.dialogController.open();
          }
        })
        .id('Video')
      MenuItem({
        startIcon: $r("app.media.camera"),
        content: $r('app.string.publish_multimedia_updates_review')
      })
        .onClick(() => {
          promptAction.showToast({
            message: $r('app.string.publish_multimedia_updates_other_function'),
          });
        })
      MenuItem({
        startIcon: $r("sys.media.ohos_ic_public_camera"),
        content: $r('app.string.publish_multimedia_updates_live')
      })
        .onClick(() => {
          promptAction.showToast({
            message: $r('app.string.publish_multimedia_updates_other_function'),
          });
        })
    }
    .width($r('app.string.publish_multimedia_updates_layout_40'))
  }

  @Builder
  MyADD() {
    Image($r('sys.media.ohos_ic_public_add'))
      .bindMenu(this.MyMenu())
      .width($r('app.string.publish_multimedia_updates_layout_40'))
      .height($r('app.string.publish_multimedia_updates_layout_40'))
      .position({ top: 20, right: 5 })
      .id('add_button')
  }

  @Builder
  Camera() {
    Image($r('sys.media.ohos_ic_public_camera'))
      .width($r('app.string.publish_multimedia_updates_layout_30'))
      .position({ top: 15, left: 10 })
  }

  build() {
    Row() {
      Tabs({ controller: this.controller1, index: 1 }) {
        TabContent() {
        }.tabBar(this.Camera())


        TabContent() {
          Column() {
            List({ space: Constants.LIST_SPACE, scroller: this.listScroller }) {
              // TODO:高性能知识点:列表数据较多,不需要全部渲染上屏,采用LazyForEach。
              LazyForEach(this.commentList, (moment: FriendMoment) => {
                ListItem() {
                  OneMoment({ moment: moment });
                }
              }, (moment: FriendMoment) => moment.id)
            }
            // TODO:高性能知识点:为保证滑动流畅,采用cachedCount缓存前后节点。
            .cachedCount(this.cachedCountNumber)
            .width($r('app.string.publish_multimedia_updates_layout_100'))
            .layoutWeight(1)
            .listDirection(Axis.Vertical)
            .divider({
              strokeWidth: $r('app.integer.publish_multimedia_updates_divider_width'),
              color: $r('app.color.publish_multimedia_updates_divider_color'),
              startMargin: $r('app.integer.publish_multimedia_updates_list_divider_margin'),
              endMargin: $r('app.integer.publish_multimedia_updates_list_divider_margin')
            })
          }
          .height($r('app.string.publish_multimedia_updates_layout_100'))
          .width($r('app.string.publish_multimedia_updates_layout_100'))
        }.tabBar($r('app.string.publish_multimedia_updates_following'))
        .height($r('app.string.publish_multimedia_updates_layout_100'))
        .width($r('app.string.publish_multimedia_updates_layout_100'))


        TabContent() {
          Column()
            .width($r('app.string.publish_multimedia_updates_layout_100'))
            .height($r('app.string.publish_multimedia_updates_layout_100'))
            .backgroundColor(Color.Blue)
        }.tabBar($r('app.string.publish_multimedia_updates_for_you'))


        TabContent() {
        }.tabBar(this.MyADD())
      }
      .onContentWillChange((currentIndex, comingIndex) => {
        if (comingIndex == 0 || comingIndex == 2 || comingIndex == 3) {
          promptAction.showToast({
            message: $r('app.string.publish_multimedia_updates_other_function'),
          });
          return false
        }
        if (comingIndex == 0) {
          return false
        }
        return true
      })
      .vertical(false)
      .barMode(BarMode.Fixed)
      .height($r('app.string.publish_multimedia_updates_layout_100'))
      .width($r('app.string.publish_multimedia_updates_layout_100'))
      .barWidth($r('app.integer.publish_multimedia_updates_list_barwidth'))
      .barHeight($r('app.integer.publish_multimedia_updates_list_barheight'))
    }
    .alignItems(VerticalAlign.Center)
    .height($r('app.string.publish_multimedia_updates_layout_100'))
    .width($r('app.string.publish_multimedia_updates_layout_100'))
  }
}

更多关于HarmonyOS鸿蒙Next中请问一下各位大佬@ObservedV2 + @Trace在V1页面上混合使用时,为什么UI没有自动刷新页面又没报错?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

V1、V2混用时,有的错误能正常提示,有的可能不会提示,有的只是效果不正常,但是不影响程序运行。

个人建议分开使用,且以后估计会对V2新增更多功能,V1会慢慢淘汰掉。

更多关于HarmonyOS鸿蒙Next中请问一下各位大佬@ObservedV2 + @Trace在V1页面上混合使用时,为什么UI没有自动刷新页面又没报错?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


感谢回答,如果上面问题没解决,可能试试整个页面迁移到V2。

在HarmonyOS鸿蒙Next中,@ObservedV2@Trace混合使用时,UI未自动刷新且无报错,可能是由于以下原因:

  1. 状态管理不一致:@ObservedV2@Trace可能未正确同步状态,导致UI未感知到数据变化。
  2. 生命周期问题:页面生命周期未正确触发状态更新,建议检查onPageShowonPageHide等生命周期方法。
  3. 依赖关系未建立:@Trace可能未正确绑定到@ObservedV2的状态,导致依赖关系未建立,UI无法自动刷新。

建议检查状态管理和依赖关系,确保数据变化能正确触发UI更新。

回到顶部