HarmonyOS Next中通过onIdle机制预创建组件的示例代码有吗?

阅读 589
avatarAI BotBETA
在HarmonyOS Next中,通过`onIdle`机制预创建组件的示例代码如下:

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.bundle.IBundleManager;
import ohos.security.SystemPermission;
import ohos.utils.zonal.ZoneId;

public class MyAbility extends Ability {

@Override
protected void onStart(Intent intent) {
    super.onStart(intent);
    super.setUIContent(ResourceTable.Layout_ability_main);

    // 获取IdleManager实例
    IdleManager idleManager = getIdleManager();

    // 设置onIdle回调,预创建组件
    idleManager.onIdle(new IdleCallback() {
        @Override
        public void onIdle() {
            // 预创建组件,例如Text组件
            Text preCreatedText = new Text(MyAbility.this);
            preCreatedText.setText("Pre-created Text Component");
            // 将预创建的组件添加到UI中或进行其他处理
            // 注意:这里只是示例,实际使用中可能需要更复杂的逻辑来管理预创建的组件
        }
    }, IdleConfig.DEFAULT_IDLE_TIME, ZoneId.systemDefault());
}

@Override
protected void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_CODE_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == IBundleManager.PERMISSION_GRANT) {
            // 权限被授予,可以执行相关操作
        } else {
            // 权限被拒绝,处理相应逻辑
        }
    }
}

// 确保在需要时请求相关权限,例如SYSTEM_ALERT_WINDOW权限(根据实际需求调整)
private void requestPermission() {
    if (verifySelfPermission(SystemPermission.SYSTEM_ALERT_WINDOW) != IBundleManager.PERMISSION_GRANT) {
        requestPermissionsFromUser(
            new String[]{SystemPermission.SYSTEM_ALERT_WINDOW},
            REQUEST_CODE_PERMISSION
        );
    }
}

private static final int REQUEST_CODE_PERMISSION = 1;

}


请注意,上述代码是一个简单的示例,展示了如何通过`onIdle`机制预创建组件。在实际应用中,你可能需要更复杂的逻辑来管理预创建的组件,并确保在合适的时机将它们添加到UI中。此外,如果预创建的组件需要特定的权限,请确保在代码中请求这些权限。
1 个回答

将对组件预创建进行优化,把预创建分摊到帧尾的空闲时间中进行。

  1. 通过常规预创建抓取Trace,获取单个组件预创建耗时,示例代码中单个组件预创建耗时最长在1ms左右。
  2. 继承抽象类FrameCallback,实现帧回调类,在构造器中传入预创建的数据,并实现onIdle接口。

    export class IdleCallback extends FrameCallback {
      private uiContext: UIContext;
      // 已经创建的子组件数量
      private todoCount: number = 0;
      private viewItems: ViewItem[] = [];
    
      /**
    * @param context 上下文对象,用于将帧回调传递到下一帧
    * @param preBuildData 预创建组件的数据列表,用于确认预创建组件的数量和相关信息,可根据业务需求自行修改或设置固定值
    */
      constructor(context: UIContext, preBuildData: ViewItem[]) {
     super();
     this.uiContext = context;
     this.viewItems = preBuildData;
      }

    系统通过onIdle回调方法,将帧尾空闲时间通过参数idleTimeInNano(单位:ns)传递出来。在接收到帧尾空闲时间后,如果有需要预创建的组件,可根据单个组件的预创建耗时,设置预创建的剩余空闲时间上限(示例代码中设置了1ms)。

    // onIdle回调,返回帧尾空闲时间idleTimeInNano。
    onIdle(idleTimeInNano: number): void {
    
      // 当预创建的组件数量已经超过模拟数据的数量,则停止预创建
      if (this.todoCount >= this.viewItems.length) {
     return;
      }
      // 当前时间,后续用于计算本帧剩余空闲时间。
      let cur: number = systemDateTime.getTime(true);
      // 帧尾空闲时间,后续用于计算本帧剩余空闲时间。
      let timeLeft = idleTimeInNano;
      // 当帧尾空闲时间大于1ms时,执行预创建。
      // 此处空闲时间限制设置了1ms,即空闲时间少于1ms时,本帧不再进行组件的预创建,而是将帧回调传递到下一帧,开发者可以根据自身业务、组件复杂度进行设置,预留足够的空闲时间。
      while (timeLeft >= 1000000) {

    当剩余空闲时间足够创建组件时,在此帧中进行组件预创建,并不断更新当前帧的剩余空闲时间

    hiTraceMeter.startTrace('onIdle_prebuild', 1);
    // 进行组件预创建
    NodePool.getInstance()
      .preBuild('reuse_type_', this.viewItems[this.todoCount], flowItemWrapper, this.uiContext);
    hiTraceMeter.finishTrace('onIdle_prebuild', 1);
    // 预创建完成后,更新本帧剩余空闲空闲时间。
    let now = systemDateTime.getTime(true);
    timeLeft = timeLeft - (now - cur);
    cur = now;
    this.todoCount++;
    // 当预创建的组件数量已经超过模拟数据的数量,则停止预创建
    if (this.todoCount >= this.viewItems.length) {
      return;
    }

当当前帧剩余空闲时间不足以创建组件时,通过postFrameCallback方法,将帧回调传递到下一帧,继续进行剩余组件的预创建。

// 如果组件预创建没有完成,则将帧回调传递到下一帧,并在下一帧中继续进行组件的预创建。
if (this.todoCount < this.viewItems.length) {
  this.uiContext.postFrameCallback(this);
}

在冷启动时通过帧回调的方式预创建组件。

@Entry
@Component
struct Index {
  // ...
  aboutToAppear(): void {
    // ...
    // 获取模拟数据
    let viewItems: ViewItem[] = [];
    viewItems.push(...furnitureData());
    viewItems.push(...natureData());
    let context = this.getUIContext();
    // 开启帧回调
    context.postFrameCallback(new IdleCallback(context, viewItems));
  }

  // ...
}

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进