本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、背景

传统启动方式的痛点
  • 性能瓶颈:所有初始化任务集中在 UIAbility 的 onCreate 中,主线程顺序执行

  • 代码混乱:任务依赖关系复杂,难以维护和扩展

  • 启动延迟:任务过多时严重影响应用启动速度

AppStartup 解决方案
  • 异步并行:支持任务在异步线程执行

  • 依赖管理:通过配置文件明确任务执行顺序和依赖关系

  • 代码清晰:配置与实现分离,提高可维护性

  • 灵活控制:支持自动/手动两种执行模式

二、运行机制

执行模式

模式 触发时机 适用场景
自动模式 AbilityStage 构造过程中 应用主流程必需的初始化任务
手动模式 调用 startupManager.run() 按需初始化的非核心任务

框架执行流程

  1. 配置加载:系统读取 startup_config.json 配置文件

  2. 依赖分析:解析任务间的依赖关系图

  3. 任务调度:根据依赖关系并行或串行执行任务

  4. 结果回调:通过监听器通知执行结果

三、约束条件

模块支持

模块类型 自动模式 手动模式 启动方式
Entry HAP 支持 支持 主动执行
Feature HAP  API 20+ API 20+ 主动执行
HSP 不支持 支持 被 HAP 依赖拉起
HAR 不支持 支持 被 HAP 依赖拉起
so 预加载 支持 支持 Native 库加载

约束

  • 必须配置:在 module.json5 中显式开启启动框架

  • 不支持场景:ExtensionAbility 组件(会带来额外开销)

  • 依赖限制:任务之间不允许循环依赖

  • 文件混淆:如开启文件名混淆,需将启动文件加入白名单

四、开发流程

第一步:创建配置文件

1.1 在 module.json5 中引用
{
  "module": {
    "name": "entry",
    "type": "entry",
    "appStartup": "$profile:startup_config"
  }
}
1.2 创建启动框架配置文件

文件位置:resources/base/profile/startup_config.json

{
  "startupTasks": [...],                       // 启动任务配置
  "appPreloadHintStartupTasks": [...],          // so预加载任务
  "configEntry": "./ets/startup/AppStartupConfig.ets"     // 启动参数配置
}

第二步:配置启动参数

2.1 启动参数配置文件

创建 ets/startup/AppStartupConfig.ets

import { StartupConfig, StartupConfigEntry, StartupListener } from '@kit.AbilityKit';

export default class ApplicationStartupConfig extends StartupConfigEntry {
  onConfig() {
    const startupCompletionHandler = (error) => {
      if (error) {
        console.error(`Startup framework completed with error: ${error.code}, ${error.message}`);
      } else {
        console.info('All startup tasks completed successfully');
      }
    };

    const frameworkListener: StartupListener = {
      'onCompleted': startupCompletionHandler
    };

    const frameworkConfig: StartupConfig = {
      'timeoutMs': 15000,  // 15秒超时
      'startupListener': frameworkListener
    };
    
    return frameworkConfig;
  }
  
  // 自定义匹配规则(API 20+)
  onRequestCustomMatchRule(want: Want): string {
    // 根据启动参数返回匹配规则
    if (want?.parameters?.launchSource === 'notification') {
      return 'notification_launch';
    }
    if (want?.parameters?.fromWidget === true) {
      return 'widget_launch';
    }
    return '';
  }
}

第三步:定义启动任务

3.1 启动任务配置文件
{
  "startupTasks": [
    {
      "name": "DatabaseInitializer",
      "srcEntry": "./ets/startup/DatabaseInitTask.ets",
      "dependencies": [
        "LoggerInitializer",
        "ConfigLoader"
      ],
      "runOnThread": "taskPool",
      "waitOnMainThread": false,
      "excludeFromAutoStart": false,
      "matchRules": {
        "uris": [
          "app://com.example.myapp/main"
        ],
        "customization": [
          "critical_launch"
        ]
      }
    },
    {
      "name": "LoggerInitializer", 
      "srcEntry": "./ets/startup/LoggerInitTask.ets",
      "runOnThread": "mainThread",
      "waitOnMainThread": true,
      "excludeFromAutoStart": false
    }
  ]
}
3.2 启动任务属性
属性 类型 必选 说明
name string 任务唯一标识,推荐与类名一致
srcEntry string 任务实现文件路径
dependencies string[] 依赖的任务名称数组
runOnThread string 执行线程:mainThread 或 taskPool
waitOnMainThread boolean 主线程是否等待任务完成
excludeFromAutoStart boolean 是否排除自动模式(HSP/HAR 必须为 true)
matchRules object 任务匹配规则(API 20+)

第四步:实现启动任务

4.1 启动任务基类实现
import { StartupTask, common } from '@kit.AbilityKit';

@Sendable
export default class DatabaseInitTask extends StartupTask {
  constructor() {
    super();
  }

  // 核心初始化方法
  async init(context: common.AbilityStageContext) {
    console.info('DatabaseInitTask: Starting database initialization');
    
    // 模拟数据库初始化
    await this.initializeDatabase();
    console.info('DatabaseInitTask: Database initialized successfully');
    
    return { status: 'success', message: 'Database ready' };
  }

  // 依赖任务完成回调
  onDependencyCompleted(dependentTask: string, completionResult: Object): void {
    console.info(`DatabaseInitTask: Dependency ${dependentTask} completed with result: ${JSON.stringify(completionResult)}`);
    
    // 根据依赖任务结果决定后续操作
    if (dependentTask === 'LoggerInitializer') {
      this.setupDatabaseLogging();
    }
  }

  // 具体的初始化逻辑
  private async initializeDatabase(): Promise<void> {
    // 数据库连接、表创建等操作
    return new Promise((resolve) => {
      setTimeout(() => {
        console.info('Database initialization completed');
        resolve();
      }, 500);
    });
  }

  private setupDatabaseLogging(): void {
    console.info('Database logging system configured');
  }
}

第五步:配置 so 预加载任务

5.1 so 预加载配置
{
  "appPreloadHintStartupTasks": [
    {
      "name": "native_image_processor",
      "srcEntry": "libimage_processing.so",
      "dependencies": [
        "native_core_utils"
      ],
      "runOnThread": "taskPool",
      "excludeFromAutoStart": false,
      "matchRules": {
        "uris": [
          "app://com.example.myapp/editor"
        ]
      }
    },
    {
      "name": "native_core_utils", 
      "srcEntry": "libcore_utils.so",
      "runOnThread": "taskPool",
      "excludeFromAutoStart": false
    }
  ]
}
5.2 so 任务特殊约束
  • 线程限制:只能在 taskPool 线程执行

  • 执行时间:不宜过长,避免影响主线程

  • 逻辑限制:不建议在 so 加载回调中运行复杂业务逻辑

五、多模块协同启动

跨模块任务依赖

支持 HAP、HSP、HAR 之间的任务依赖管理:

模块配置示例

HAP (entry) 配置

{
  "startupTasks": [
    {
      "name": "MainAppInitializer",
      "srcEntry": "./ets/startup/MainAppInit.ets", 
      "dependencies": [
        "HSP1_NetworkService",
        "HAR1_Analytics"
      ],
      "runOnThread": "taskPool"
    }
  ]
}

HSP1 配置

{
  "startupTasks": [
    {
      "name": "HSP1_NetworkService",
      "srcEntry": "./ets/startup/NetworkInit.ets",
      "dependencies": ["HAR1_Security"],
      "runOnThread": "taskPool",
      "excludeFromAutoStart": true  // HSP 必须为手动模式
    }
  ]
}

六、高级功能

手动模式执行

在 UIAbility 中手动执行
import { AbilityConstant, UIAbility, Want, startupManager } from '@kit.AbilityKit';

export default class MainAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    console.info('MainAbility onCreate');
    
    // 手动执行特定任务
    const manualTasks = ['LazyFeatureInitializer', 'BackgroundServiceStarter'];
    
    startupManager.run(manualTasks)
      .then(() => {
        console.info(`Manual startup tasks completed: ${manualTasks.join(', ')}`);
      })
      .catch((error) => {
        console.error(`Manual startup failed: ${error.message}`);
      });
  }
}
在页面中按需执行
import { startupManager } from '@kit.AbilityKit';

@Entry
@Component
struct FeaturePage {
  @State featureTasks: Array<string> = ["AdvancedFeatureInitializer"];
  @State nativeLibraries: Array<string> = ["libadvanced_feature.so"];

  build() {
    Column() {
      Button('Initialize Advanced Features')
        .onClick(() => {
          // 检查是否已初始化
          if (!startupManager.isStartupTaskInitialized("AdvancedFeatureInitializer")) {
            startupManager.run(this.featureTasks);
          }
          
          if (!startupManager.isStartupTaskInitialized("libadvanced_feature.so")) {
            startupManager.run(this.nativeLibraries);
          }
        })
    }
  }
}

匹配规则类型

规则类型 匹配依据 适用场景
uris Want 中的 uri 属性 特定页面直达
actions Want 中的 action 属性 特定操作流程
insightIntents 意图名称 智能场景识别
customization 自定义规则 复杂业务逻辑

任务设计原则

  1. 单一职责:每个任务功能聚焦,便于并发执行

  2. 依赖最小化:减少任务间依赖,缩短关键路径

  3. 线程合理分配

    • I/O 密集型:使用 taskPool

    • UI 相关:使用 mainThread

  4. 按需加载:非核心功能使用手动模式

配置建议

{
  "startupTasks": [
    {
      "name": "CriticalCore",
      "srcEntry": "./ets/startup/CriticalCore.ets",
      "runOnThread": "mainThread",
      "waitOnMainThread": true  // 核心任务主线程等待
    },
    {
      "name": "AsyncDataPreload", 
      "srcEntry": "./ets/startup/DataPreload.ets",
      "dependencies": ["CriticalCore"],
      "runOnThread": "taskPool",
      "waitOnMainThread": false  // 异步任务不阻塞主线程
    }
  ]
}
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐