目录

应用快启

概述

随着应用功能不断丰富,启动阶段往往需要完成进程创建、运行时初始化、模块加载、资源解析、首屏构建等一系列操作。当冷启动链路较长或启动阶段资源、模块加载占比较高时,将导致用户在首屏等待时间变长,进而影响应用体验和留存表现。

从API version 24开始,系统提供应用快启机制。该机制通过提前完成启动阶段中可复用流程的初始化工作,在用户再次启动应用时,复用相关启动初始化结果,减少重复初始化和加载开销,缩短启动链路耗时,有助于提升应用启动速度和稳定性。

应用快启机制的特点:

开发者可以从以下维度判断应用是否适合接入快启能力:

基本概念

约束限制

实现原理

快启技术会提前完成启动流程中可复用部分的初始化工作。应用启动时,可复用相关初始化结果,从而跳过这部分启动流程,达到启动加速的目标。如下图所示,快启相较于普通启动可跳过启动过程中的部分阶段,从而减少启动时延:

包含在快启点内的流程有:AbilityStage模块加载、AbilityStage.onCreate和UIAbility模块加载。其中,在模块加载过程中将执行部分代码,包括顶层代码(top level)、so的constructor和类静态变量初始化等。

快启适配

[h2]快启风险操作

快启会跳过部分启动流程。为了保证数据一致性和状态正确,开发者需要消除快启初始化流程中的风险操作,才能保障快启后应用数据的正确性。

风险操作的实例如下:

[h2]将快启风险操作后置到快启点之外

系统为开发者提供了新的回调接口onAboutToCreateAbility()。该接口在AbilityStage.onCreate()执行完毕后触发,但不参与快启初始化过程。无论是否开启应用快启功能,该回调均会被调用。

示例1: AbilityStage.onCreate中存在快启风险操作。

export class AppAbilityStage extends AbilityStage {
    onCreate() {
        this.readFile();
    }
    readFile() {
        // 从磁盘读取文件
    }
}

建议:

  1. 将快启风险操作后置到AbilityStage.onAboutToCreateAbility。

    export class AppAbilityStage extends AbilityStage {
        onAboutToCreateAbility() {
            this.readFile();
        }
    }
  2. 调整业务逻辑时,需要考虑时序依赖,保障业务逻辑正确性。

  3. AbilityStage.onCreate()是首个包含较多业务逻辑的生命周期回调。若该回调中的业务不易拆分,建议开发者在首次适配时,将AbilityStage.onCreate()的内容整体移至onAboutToCreateAbility()。后续可通过业务前移扩大收益。

示例2: 顶层代码中存在快启风险操作。

以下示例在顶层代码中实例化类,并最终导致文件访问:

class ClassA {
    constructor() {
        this.readFile();
    }

    readFile() {
        // 从磁盘读取文件
    }
}

let tmp = new ClassA();

建议:

  1. 顶层代码会随import该模块而执行,所以在时序上顶层代码与首个调用者绑定,属于隐式且不可控的调用,修改时容易造成调用时序混乱,所以建议在非顶层代码中实现业务逻辑。

  2. 具体到快启特性,系统要求应用模块不可以在顶层代码执行快启风险操作,而是要根据业务逻辑调整到生命周期回调中执行。

示例3: C++的构造函数中存在快启风险操作。

static napi_module OpenPlatformModule = {
    .nm_version = 1,
    .nm_flags = 100,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "openplatform",
    .nm_priv = ((void *)0),
    .reserved = {0}
};

void read_file() {
    // 从磁盘读取文件
}

extern "C" __attribute__((constructor)) void RegisterOpenPlatformModule(void) {
    napi_module_register(&OpenPlatformModule);
    read_file();
}

建议:

  1. 逐一检查启动过程中加载的so。constructor中不存在快启风险操作的so在AbilityStage.onCreate中进行dlopen,以扩大快启收益。

  2. 存在风险操作constructor的so,需要放到UIAbility等快启点之外的生命周期中调用。

示例4: 类静态变量初始化中存在快启风险操作。

以下示例中存在两类静态初始化:一是静态变量初始化,会读取文件;二是静态代码块执行,会进行网络访问。

export class AppAbilityStage extends AbilityStage {
    private a = 1;
    static data = AppAbilityStage.readFile();
    static {
        AppAbilityStage.netAccess();
    }
    static readFile() {
        // 从磁盘读取文件
    }
    static netAccess() {
        // 网络访问
    }
}

建议:根据业务逻辑进行调整,将快启风险操作移出快启点。

[h2]在更新回调接口中更新数据

考虑到实际调整业务逻辑的困难,部分对外数据交互难以剥离。快启机制为开发者提供新的回调接口onLaunchFromHyperSnap(),该回调接口仅在快启流程(而不是快启初始化流程)中执行,正常冷启动不执行该回调。开发者可以在该回调接口中重新请求外部数据进行同步,保证数据一致性。

export class AppAbilityStage extends AbilityStage {
    onCreate() {
        this.initLanguage(language);
    }
    initLanguage(language) {
        readFile(); // AbilityStage.onCreate中存在快启风险操作
    }
    readFile() {
        // 从磁盘读取文件
    }
}
export class AppAbilityStage extends AbilityStage {
    onLaunchFromHyperSnap() {
        this.updateLanguage(); // 在onLaunchFromHyperSnap中进行更新
    }
    updateLanguage() {
        readFile();
    }
}

通过应用侧云推开关开启或关闭快启功能

云推开关是一种通过云端在线配置、动态开启或关闭应用特定功能的机制。

借助setHyperSnapEnabled(),应用可以根据需要关闭快启功能,直至云推开关重新开启。

云推开关的基本规格:

云推开关使用示例:

通过上述实现,可保障应用更新后继续使用快启特性。

export class LauncherAbility extends UIAbility {
    onCreate() {
        // ...
    }

    onConfigChange(key: string, value: string) {
        if (key == "enable_hyper_snap") {
            if (value == "true") {
                setHyperSnapEnabled(true);
            } else {
                setHyperSnapEnabled(false);
            }
        }
    }
}

export class AppAbilityStage extends AbilityStage {
    onCreate() {
        const hyperSnapConfig = this.readConfigFromDB();
        if (hyperSnapConfig === "true") {
            setHyperSnapEnabled(true);
        } else {
            setHyperSnapEnabled(false);
        }
    }

    readConfigFromDB() {
        // 从数据库读取setHyperSnapEnabled参数
    }
}

通过应用主动重置快启初始化结果

系统对外提供了requestRebuildHyperSnap()接口,该接口支持应用在自己的业务逻辑中主动调用,清理当前快启初始化结果,在满足条件时重新进行快启初始化。

export class LauncherAbility extends UIAbility {
    onCreate() {
        // ...
        try {
            // ...
        } catch (error) {
            // ...
            requestRebuildHyperSnap(); // 开发者可根据业务在报错时重新生成快启初始化结果
            // ...
        }
    }
}

通过调整业务逻辑提升快启加速收益

纳入快启点的启动逻辑越多,快启收益通常越明显。开发者可以对整个启动流程进行梳理和分析,将适合纳入快启点的启动逻辑(即不含快启风险操作),在保障业务逻辑正确性的条件下前置到快启点内,扩大应用快启技术提升启动性能的收益。

快启接入的辅助工具

为帮助开发者定位需要适配和修改的内容,系统提供了配套插件工具。该工具基于代码扫描,识别具有快启风险的代码,并报告给开发者进行修正,节省人工排查工作量,提升应用适配快启的效率。

示例代码

针对应用快启启动开发,可参考以下相关实例: