• Lv0
    粉丝0

积分5 / 贡献0

提问1答案被采纳0文章0

作者动态

    lazyforeach快速修改数据的时候崩溃

    chinabosh 显示全部楼层 发表于 2024-6-13 16:14:01

    【问题描述】

    1. 介绍问题现象和发生的背景 应用需要快速显示一些数据

    2. 相关的代码(请勿使用截图)

      export class DataSource implements IDataSource {
        private listeners: DataChangeListener[] = [];
      
        private origin: string[]
        private dataChange: () => void
      
        constructor(data: string[]) {
          this.origin = data
        }
      
        totalCount(): number {
          return this.origin.length - 1
        }
      
        getData(index: number): any {
          return this.origin[index]
        }
      
        onDataChange(listener: () => void) {
          this.dataChange = listener
        }
      
        registerDataChangeListener(listener: DataChangeListener): void {
          if (this.listeners.indexOf(listener) < 0) {
            console.info('add listener');
            this.listeners.push(listener);
          }
        }
      
        unregisterDataChangeListener(listener: DataChangeListener): void {
          const pos = this.listeners.indexOf(listener);
          if (pos >= 0) {
            console.info('remove listener');
            this.listeners.splice(pos, 1);
          }
        }
      
        // 通知LazyForEach组件需要重载所有子组件
        notifyDataReload(): void {
          this.listeners.forEach(listener => {
            listener.onDataReloaded();
          })
          this.dataChange()
        }
      
        // 通知LazyForEach组件需要在index对应索引处添加子组件
        notifyDataAdd(index: number): void {
          this.listeners.forEach(listener => {
            listener.onDataAdd(index);
          })
          this.dataChange()
        }
      
        // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
        notifyDataChange(index: number): void {
          this.listeners.forEach(listener => {
            listener.onDataChange(index);
          })
          this.dataChange()
        }
      
        // 通知LazyForEach组件需要在index对应索引处删除该子组件
        notifyDataDelete(index: number): void {
          this.listeners.forEach(listener => {
            listener.onDataDelete(index);
          })
          this.dataChange()
        }
      
        // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
        notifyDataMove(from: number, to: number): void {
          this.listeners.forEach(listener => {
            listener.onDataMove(from, to);
          })
          this.dataChange()
        }
      }
      
      this.mInputDataSource = new DataSource(this.mInputData)
      setInterval(() => {
            let data = Date.now().toString()
            if (this.mInputData.length == 100) {
              this.mInputData.pop()
              this.mInputDataSource.notifyDataDelete(this.mInputData.length)
            }
            this.mInputData.unshift(data)
            this.mInputDataSource.notifyDataAdd(0)
            this.mInputDataSource.notifyDataReload()
          }, 50)
      
      List({ scroller: this.scroller }) {
                  LazyForEach(this.inputData, (item: string, index: number) => {
                    ListItem() {
                       Text(item)
                         .fontSize(16)
                         .fontColor(Color.White)
                    }.padding({ top: 5, bottom: 5 })
                    .reuseId('input list')
                  }, (item: string, index: number) => {
                    return item + index.toString()
                  })
                }.attributeModifier(new SettingListAttribute())
                .padding(20)
                .layoutWeight(1)
                .cachedCount(10)
    3. 运行结果、错误截图

      image.png

      image.png

    4. 我尝试过的解决方法和结果

      尝试过降低更新数据频率,但是只是让崩溃来的晚一些

    5. 我想要达到的结果

      不崩溃

    【运行环境】

    硬件:rk3588 ROM版本:OpenHarmony 4.1.7.5 DevEvoStudio版本:4.1.3.501 SDK版本:11(full-sdk)

    您尚未登录,无法参与评论,登录后可以:
    参与开源共建问题交流
    认同或收藏高质量问答
    获取积分成为开源共建先驱

    精彩评论1

    chinabosh

    沙发 发表于 2024-6-14 10:31:57
    经过排查发现,不是lazyforeach的问题!!!
    是其他地方错误使用了napi_create_external_arraybuffer,如下:
    1.      napi_finalize finalize_cb;
    2.     if (napi_ok !=
    3.         napi_create_external_arraybuffer(
    4.             env, buffer_data, mDataSize, finalize_cb, nullptr, &ret)) {
    5.         LOGE("ArraybufferType", "napi_create_external_arraybuffer failed");
    6.         return nullptr;
    7.     }
    复制代码


    按照我的推测:lazyforeach在快速更新列表的时候,会较快的触发内存回收的操作,而napi_create_external_arraybuffer这里的finalize_cb没有执行内存回收操作,导致data成野指针,从而导致内存回收时崩溃!!!
    正确使用napi_create_external_arraybuffer如下
    1. if (napi_ok !=
    2.         napi_create_external_arraybuffer(
    3.             env, buffer_data, mDataSize, [](napi_env env, void *data, void *hint) { free(data); }, nullptr, &ret)) {
    4.         LOGE("ArraybufferType", "napi_create_external_arraybuffer failed");
    5.         return nullptr;
    6.     }
    复制代码

    Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

    返回顶部