Stage模型概述

  • 详细内容可以看一下鸿蒙开发者文档
    image.png
  • 模块是应用的基本功能单元,包含源代码、资源以及配置文件等内容
  • 模块分为两大类,像entry这样的模块称为Ability Module能力模块,而通用的资源等可以放在一个模块当中,这样的模块成为Library Module,Ability Module就可以去引用Library的模块了。
  • 整个源码会被编译打包成APP,为了降低不同功能模块之间的耦合,每一个模块都是可以独立编译和运行的,所有的Ability Module会被编译成HAP文件,而Library Module会被编译成HSP文件。
  • 一个应用有且只有一个Entry类型的HAP文件,而Feature类型可以有多个。
  • 所有HAP文件最后会打包成Bundle文件,最后一起打包成安装包文件。Bundle name是整个应用的唯一标识。
  • HAP在运行时会创建一个名为Ability Stage的实例,理解为应用组件的“舞台”。
  • 因为Ability和窗口的分割,可以实现对不同设备窗口的单独裁切适配。

应用配置文件

  • 鸿蒙应用的配置文件有两类:
  • 第一类值针对这个应用的全局配置文件,在AppScope/app.json5
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //app.json5全局配置文件
    {
    "app": {
    "bundleName": "com.example.myapplication", //是应用的唯一标识,不与其他应用重复,使用域名倒置的方式命名
    "vendor": "example",
    "versionCode": 1000000, //数字型的版本号
    "versionName": "1.0.0", //字符型的版本号
    "icon": "$media:app_icon", //应用图标
    "label": "$string:app_name" //应用描述
    }
    }
  • 第二类是在每个模块里,在每个模块的src/main/module.json5
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    //module.json5模块配置文件
    {
    "module": {
    "requestPermissions": [ //系统权限申请
    {
    "name": "ohos.permission.INTERNET"
    }
    ],
    "name": "entry", //模块名称
    "type": "entry", //模块类型,entry入口型、feature功能型、shared共享型
    "description": "$string:module_desc", //当前模块的描述,读取的是base/element/string.json
    "mainElement": "EntryAbility", //入口ability
    "deviceTypes": [ //设备类型
    "phone",
    "tablet"
    ],
    "deliveryWithInstall": true, //跟随APP安装,Entry类型必须安装,feature可选
    "installationFree": false,
    "pages": "$profile:main_pages", //模块中的所有页面,读取的是base/profile/main_pages.json
    "abilities": [ //可以有多个ability,以数组的形式写出
    {
    "name": "EntryAbility", //ability的名称
    "srcEntry": "./ets/entryability/EntryAbility.ts", //ability的源码位置
    "description": "$string:EntryAbility_desc", //ability的描述
    "icon": "$media:icon", //ability的图标
    "label": "$string:EntryAbility_label", //当前ability的文字描述
    //由于这是入口ability,所以图标和文字描述也就是桌面显示的
    "startWindowIcon": "$media:icon", //应用启动时的图标
    "startWindowBackground": "$color:start_window_background", //应用启动时的图标背景色
    "exported": true,
    "skills": [ //功能的声明
    {
    "entities": [
    "entity.system.home"
    ],
    "actions": [
    "action.system.home"
    ]
    }
    ]
    }
    ]
    }
    }

UIAbility生命周期

image.png

  • 以微信为例,进入微信会自动创建(Create)一个UIAbility,因为是入口所有会自动设置为前台(Foreground)。
  • 当打开小程序或者视频号等独立功能时,会再次创建(Create)一个UIAbility,同时原本的UIAbility会被设置为后台(Background)。查看手机后台可以看到两个微信。
  • 当不使用的时候可以直接去除后台(Destroy)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // src/main/ets/entryability/EntryAbility.ts
    import UIAbility from '@ohos.app.ability.UIAbility';
    import hilog from '@ohos.hilog';
    import window from '@ohos.window';

    export default class EntryAbility extends UIAbility { //继承了UIAbility
    onCreate(want, launchParam) { //当被创建时
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); //hilog是日志
    //info是日志级别,还有debug、error等等
    //0x0000是用来标识的参数,'testTag'是文字标记,'%{public}s'占位符,public为公开,最后是日志内容
    }

    onDestroy() { //当被销毁时
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
    }

    onWindowStageCreate(windowStage: window.WindowStage) { //当WindowStage被创建时
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages/Index', (err, data) => { //打开首页
    if (err.code) {
    hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
    return;
    }
    hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
    }

    onWindowStageDestroy() { //当WindowStage被销毁时
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
    }

    onForeground() { //在前台时
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
    }

    onBackground() { //在后台时
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
    }
    }
    image.png

页面及组件生命周期

image.png

  • aboutToAppear函数是在组件被创建之后build创建之前触发,可以在这里做一些初始化和数据的准备工作。
  • onPageShow函数是当页面被展示的时候会执行,onPageHide函数是当页面被隐藏的时候会执行,onBackPress函数是点击返回的时候触发。三个一起为页面生命周期函数,可以做一些功能性的逻辑。
  • aboutToDisappear函数是组件被销毁时触发。可以在这里做一些数据保存等。
  • 用push方法跳转页面,并不会销毁组件,而是隐藏,但是replace方法会销毁组件,性能消耗大。
  • 子组件不会执行页面生命周期函数。
  • For循环刷新渲染会将每个元素都删除重新渲染,需要给每个元素添加标识才可以避免反复渲染。

UIAbility的启动模式

Singleton启动模式

  • 每一个UIAbility只存在唯一实例。是默认启动模式
  • 任务列表中只会存在一个相同的UIAbility
    image.png
  • 再次打开UIAbility只是将之前被隐藏的重新显示

standard启动模式

  • 每次启动UIAbility都会创建一个新的实例
  • 在任务列表中可能存在一个或多个相同的UIAbility
    image.png

    multiton启动模式
    和standard类似,但是每次启动UIAbility都会创建一个新的实例,而旧的会被销毁

specified启动模式

  • 每个UIAbility实例可以设置Key标示
  • 启动UIAbility时,需要指定Key,存在Key相同实例直接被拉起,不存在则创建新实例
  • 在实际应用中,可以在需要多个内容同时使用的情况下使用,例如文档编辑需要打开两个文档,并保留在后台
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    //1. 当前UIAbility调用startAbility方法拉起目标UIAbility

    //1.1 获取上下文
    context = getContext(this) as common.UIAbilityContext

    //1.2 指定要跳转的UIAbility的信息
    let want = {
    deviceID: '', //deviceId为空表示本设备
    bundleName: 'com.example.myapplication', //指定哪个应用的bundleName
    abiliyuName: 'DocumentAbility',
    moduleName: 'entry', //moduleName非必选
    parameters: {
    // getInstanceKey:自定义方法,生成目标UIAbility实例的Key
    instanceKey: this.getInstanceKey()
    }
    }

    //1.3 尝试拉起目标UIAbility实例
    this.context.startAbility(want)

    //2. 在AbilityStage的生命周期回调中为目标UIAbility实例生成Key
    export default class MyAbilityStage extends AbilityState{
    onAcceptWant(want: Want): string {
    //判断当前要拉取的是否是DocumentAbility
    if(want.abilityName === 'DocumentAbility'){
    //根据参数中的instanceKey参数拼接生成一个Key值并返回
    return `DocAbility_${want.parameters.instanceKey}`
    }
    return '';
    }
    }

    //3. 在module.json5配置文件中,通过srcEntry参数指定AbilityStage路径
    {
    "module":{
    "name": "entry",
    "type": "entry",
    "srcEntry": "./ets/myabilitystage/MyAbilityStage.ts",
    ...
    }
    }
  • 详细可以参考鸿蒙开发文档,因为太复杂了。