目录

一文带你深入了解Stage模型

1.概述

在基于Stage模型开发应用之前,开发者需要了解应用的设计机制、应用程序包结构等基础知识。

应用与应用程序包

用户应用程序泛指运行在设备的操作系统之上,为用户提供特定服务的程序,简称"应用"。一个应用所对应的软件包文件,称为"应用程序包"。

当前系统提供了应用程序包开发、安装、查询、更新、卸载的管理机制,便于开发者开发和管理应用。同时,系统还屏蔽了不同的芯片平台的差异(包括x86/ARM,32位/64位等),应用程序包在不同的芯片平台都能够安装运行,这使得开发者可以聚焦于应用的功能实现。

应用的多Module设计机制

  • 支持模块化开发 一个应用通常会包含多种功能,将不同的功能特性按模块来划分和管理是一种良好的设计方式。在开发过程中,我们可以将每个功能模块作为一个独立的Module进行开发,Module中可以包含源代码、资源文件、第三方库、配置文件等,每一个Module可以独立编译,实现特定的功能。这种模块化、松耦合的应用管理方式有助于应用的开发、维护与扩展。
  • 支持多设备适配: 一个应用往往需要适配多种设备类型,在采用多Module设计的应用中,每个Module都会标注所支持的设备类型。有些Module支持全部类型的设备,有些Module只支持某一种或几种类型的设备(比如平板),那么在应用市场分发应用包时,也能够根据设备类型做精准的筛选和匹配,从而将不同的包合理的组合和部署到对应的设备上。

工程目录结构

2.应用配置

每个应用项目的代码目录下必须包含应用配置文件,这些配置文件会向编译工具、操作系统和应用市场提供应用的基本信息。

在基于Stage模型开发的应用项目代码下,都存在一个app.json5配置文件、以及一个或多个module.json5配置文件。

app.json5配置文件主要包含以下内容:

  • 应用的全局配置信息,包含应用的Bundle名称、开发厂商、版本号等基本信息。
  • 特定设备类型的配置信息。

module.json5配置文件主要包含以下内容:

  • Module的基本配置信息,包含Module名称、类型、描述、支持的设备类型等基本信息。
  • 应用组件信息,包含UIAbility组件和ExtensionAbility组件的描述信息。
  • 应用运行过程中所需的权限信息。

配置图标与文字

打开模拟器或者真机,我们需要配置应用和桌面上的图标和文字,如何配置?

图标和标签通常一起配置,对应app.json5配置文件module.json5配置文件中的icon和label标签。

注意:

  1. DevEco Studio从5.0.3.800版本开始,不再对module.json5中的icon和label做强制校验,因此module.json5与app.json5只需要选择其一配置即可
  2. 如果两个同时存在:module.json5中的配置会覆盖app.json5中的配置

3.UIAbility 组件

1. 概述

UIAbility组件是一种包含UI的应用组件,主要用于和用户交互。

UIAbility的设计理念:

  1. 原生支持应用组件级的跨端迁移和多端协同。
  2. 支持多设备和多窗口形态。

UIAbility划分原则与建议:

UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的UIAbility。

每一个UIAbility组件实例都会在最近任务列表中显示一个对应的任务。

于开发者而言,可以根据具体场景选择单个还是多个UIAbility,划分建议如下:

  • 如果开发者希望在任务视图中看到一个任务,建议使用"一个UIAbility+多个页面"的方式,可以避免不必要的资源加载。
  • 如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,建议使用多个UIAbility实现不同的功能。

例如,即时通讯类应用中的消息列表与音视频通话采用不同的UIAbility进行开发,既可以方便地切换任务窗口,又可以实现应用的两个任务窗口在一个屏幕上分屏显示。

说明

任务视图用于快速查看和管理当前设备上运行的所有任务或应用。

声明配置

为使应用能够正常使用UIAbility,需要在module.json5配置文件abilities标签中声明UIAbility的名称、入口、标签等相关信息。

kotlin 复制代码
{
  "module": {
    // ...
    "abilities": [
      {
        "name": "EntryAbility", // UIAbility组件的名称
        "srcEntry": "./ets/entryability/EntryAbility.ets", // UIAbility组件的代码路径
        "description": "$string:EntryAbility_desc", // UIAbility组件的描述信息
        "icon": "$media:icon", // UIAbility组件的图标
        "label": "$string:EntryAbility_label", // UIAbility组件的标签
        "startWindowIcon": "$media:icon", // UIAbility组件启动页面图标资源文件的索引
        "startWindowBackground": "$color:start_window_background", // UIAbility组件启动页面背景颜色资源文件的索引
        // ...
      }
    ]
  }
}

是什么?UIAbility组件是 一种包含UI的应用组件 ,为应用提供绘制界面的窗口,主要用于和用户交互

一个应用可以 包含一个多个UIAbility组件

每一个UIAbility组件实例都会在最近任务列表中显示一个对应的任务

应用的UIAbility划分:

  • 单UIAbility -> 在手机操作系统的任务列表中只有一个任务窗口
  • 多UIAbility-> 在手机操作系统的任务列表中有多个任务窗口

场景选择:

对于开发者而言,可以根据具体场景选择单个还是多个UIAbility

  • 如果开发者希望在任务视图中看到一个任务,建议使用"一个UIAbility+多个页面"的方式,可以避免不必要的资源加载。
  • 如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,建议使用多个UIAbility实现不同的功能。

例如,微信【消息列表】与【音视频通话】采用不同的UIAbility进行开发,既可以方便地切换任务窗口,又可以实现应用的两个任务窗口在一个屏幕上分屏显示

2. 指定 UIAbility 的启动页

在UIAbility的onWindowStageCreate()生命周期回调中,通过 WindowStage 对象的 loadContent() 方法设置启动页面。

注意:

  • 设置的页面路径,需要在 main_page.json5中存在(否则会出现白屏)
  • 页面必须有一个入口组件(@Entry修饰的组件)

3.UIAbility的生命周期

当用户打开、切换和返回到应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换UIAbility类提供了一系列【回调函数】,如果需要在特定的时间添加自定义逻辑,往对应的回调函数内添加代码即可

UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态:

回调函数编写位置和作用:

执行时序图:

4.更改默认启动的UIAbility

当有多个UIAbility时,我们可以通过调整src/main/module.json5中的配置来更改默认启动的UIAbility

步骤:

  1. 创建一个新的UIAbility
  2. 调整src/main/module.json5中 ->mainElement属性指向abilities属性中的UIAbility名字
  3. 调整src/main/module.json5中 ->abilities节点中的UIAbility的"exported"为true,加上skills
ruby 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    //修改默认启动的UIAbility名
    "mainElement": "EntryAbility_demo",
    "deviceTypes": [
      "phone",
      "tablet",
      "2in1"
    ],

    //标识当前Module是否在用户主动安装的时候安装,即该Module对应的HAP是否跟随应用一起安装。
    "deliveryWithInstall": true,
    //标识当前Module是否支持免安装特性。
    //true:表示支持免安装特性,且符合免安装约束。
    "installationFree": false,
    //	标识当前Module的profile资源
    "pages": "$profile:main_pages",
    "abilities": [
      {
        // UIAbility组件的名称
        "name": "EntryAbility",
        // UIAbility组件的代码路径
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        // UIAbility组件的描述信息
        "description": "$string:EntryAbility_desc",
        // "icon": "$media:layered_image",
        // "label": "$string:EntryAbility_label",
        //UIAbility组件启动页面图标资源文件的索引
        "startWindowIcon": "$media:jd_logo",
        // UIAbility组件启动页面背景颜色资源文件的索引
        "startWindowBackground": "$color:start_window_background",

      },
      {
        "name": "EntryAbility_demo",
        "srcEntry": "./ets/entryability_demo/EntryAbility_demo.ets",
        "description": "$string:EntryAbility_demo_desc",
        "icon": "$media:layered_image",
        "label": "$string:EntryAbility_demo_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        //
        //标识当前UIAbility组件是否可以被其他应用调用。
        //true:表示可以被其他应用调用。
        "exported": true,
        //标识当前UIAbility组件或ExtensionAbility组件能够接收的Want特征集,为数组格式。
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ],
    "extensionAbilities": [
      {
        "name": "EntryBackupAbility",
        "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
        "type": "backup",
        "exported": false,
        "metadata": [
          {
            "name": "ohos.extension.backup",
            "resource": "$profile:backup_config"
          }
        ],
      }
    ]
  }
}

exported 与skills 只有一个用来说明该 UIability 具有调起其他页面的能力

5.拉起同一个模块的不同的UIAbility

同一个模块中,从一个UIAbility中拉起另一个UIAbility

举例:同EntryAbility中的一个页面中,点击按钮,拉起EntryAbility

typescript 复制代码
import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
  @Component
  struct demo {
    build() {
      Column() {
        Button('调起另一个UIAbility').onClick(() => {
          // 1. 获得上下文对象
          const context =  getContext(this) as common.UIAbilityContext
          //2. 调用startAbility()拉起secondAbility
          context.startAbility({
            bundleName: 'com.example.myapplication_3', // 包名称 AppScope/app.json5中查看
            moduleName:'entry',// 模块名称 entry/src/main/module.json5 -> module->name
            abilityName: 'EntryAbility', // ability名称 entry/src/main/module.json5 -> abilities找
            parameters:{  // 向Ability传入参数
              info:'这是entry传入的参数内容'
            }
          })
            .then(() => {
              console.log('startAbility success.');
            })
            .catch((error: BusinessError) => {
              console.log('startAbility failed.');
            });

        })
      }.width('100%').height('100%').backgroundColor(Color.Orange)
    }
  }
javascript 复制代码
 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 在onCreate生命周期里面的want参数就会自动接收拉起方传入的数据
    console.log('--->',JSON.stringify(want))

    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }

6.拉起不同模块的UIAbility

从一个UIAbility中拉起不同模块中的一个UIAbility

步骤:

  1. 创建一个新模块

--->

  1. 配置Entry启动项

  1. 编写拉起代码
typescript 复制代码
import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct demo {
  build() {
    Column() {
      Button('调起同一个模块的UIAbility').onClick(() => {
        // 1. 获得上下文对象
        const context =  getContext(this) as common.UIAbilityContext
        //2. 调用startAbility()拉起secondAbility
        context.startAbility({
          bundleName: 'com.example.myapplication_3', // 包名称 AppScope/app.json5中查看
          moduleName:'entry',// 模块名称 entry/src/main/module.json5 -> module->name
          abilityName: 'EntryAbility', // ability名称 entry/src/main/module.json5 -> abilities找
          parameters:{  // 向Ability传入参数
            info:'这是entry传入的参数内容'
          }
        })
          .then(() => {
            console.log('startAbility success.');
          })
          .catch((error: BusinessError) => {
            console.log('startAbility failed.');
          });
      })
      Button('调起跨模块的UIAbility').onClick(() => {
        // 1. 获得上下文对象
        const context =  getContext(this) as common.UIAbilityContext
        context.startAbility({
          bundleName: 'com.example.myapplication_3', // 包名称 AppScope/app.json5中查看
          moduleName:'Moudle_demo',// 模块名称 entry/src/main/module.json5 -> module->name
          abilityName: 'Moudle_demoAbility', // ability名称 entry/src/main/module.json5 -> abilities找
          parameters:{  // 向Ability传入参数
            info:'这是entry传入的参数内容'
          }
        })
      })
    }.width('100%').height('100%').backgroundColor(Color.Orange)
  }
}
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
孩子 你要相信光1 小时前
安卓edge://inspect 和 chrome://inspect调试移动设备上的网页
前端
乐闻x2 小时前
提升 React 应用性能:使用 React Profiler 进行性能调优
前端·javascript·react.js·性能优化
拾忆,想起3 小时前
Nacos命名空间Namespace:微服务多环境管理的“秘密武器”如何用?
java·运维·spring boot·spring cloud·微服务·架构
NaZiMeKiY4 小时前
HTML5前端第二章节
前端·html·html5
天若有情6734 小时前
深入浅出:HTML 中 <a> 标签嵌入链接教程
前端·html
烂蜻蜓4 小时前
HTML 样式之 CSS 全面解析
前端·css·html
冬冬小圆帽4 小时前
Webpack 优化深度解析:从构建性能到输出优化的全面指南
前端·webpack·node.js
大龄大专大前端6 小时前
JavaScript闭包的认识/应用/原理
前端·javascript·ecmascript 6
字节源流6 小时前
【SpringMVC】常用注解:@SessionAttributes
java·服务器·前端
肥肠可耐的西西公主6 小时前
前端(vue)学习笔记(CLASS 4):组件组成部分与通信
前端·vue.js·学习