Stage模型详解,UIability------Harmony OS 开发(第五期)

发布时间:2024年01月20日

stage模型

image.png

如上图所示,蓝色框内就是代表一个模块,一个工程下可以有n个模块,但只能有一个entry模块,即入口模块(核心),里面是该APP的主要功能。模块分为两种类型:Ability Module和Library Module模块,前者是能力模块,用于实现对应的页面和功能,后者是共享模块,里面的功能和已经创建的组件可以被其他模块共同调用,减少重复代码的书写。 所有模块在编译期统称为Bundle。每个模块都可以单独运行和测试

image.png

在代码运行时,每个模块都会搭建各自的"舞台",结构如上图,ArkUI Page :展示出来的UI界面,即与用户直接交互的地方,UIAbility是包含UI界面的应用组件,通过Window来将UI界面展示给用户,WindowStage是窗口的"舞台"。一个模块下可以有多个ability。

stage模型应用配置文件

image.png

image.png

app.json5 文件里面是整个APP的全局配置信息,“bundleName” 是APP对应的唯一标识。"icon"对应APP在设置中的应用管理中的应用图标,"label"对应的是应用在设置中的应用管理中的名称。

image.png

module.json5 文件是对应模块特有的配置文件,“requestPermission” 用于向用户或系统申请权限,“name” 对应的是该模块名字,“type” 对应的是该模块的类型,
“description” 用于描述该模块内容,“mainElement” 当该模块下有多个ability(UIAbility或ExtensionAbility)时,用于标识入口ability,“deviceTypes” 该模块适用的设备,
“deliveryWithInstall” 该模块是否跟着APP一同被安装(有些模块可以设置为用户选择性安装),“pages” 是存放该模块下所有的页面路径的文件,“abilities” 是该模块下所有ability的对应属性,其中的"icon"和"label"对应的是APP在桌面上的应用图标和名称,"launchType"对应该ability的启动模式

应用程序入口—UIAbility

UIAbility概述

UIAbility就是包含有用户界面的一个组件-----即应用程序的入口,通过用户界面与用户进行交互。其也是系统调度的单元

打开程序,进入用户界面,有3种方法:

1.点击桌面图标进入应用。

2.在一个应用中打开另一个应用。

3.从最近任务列表中切回应用(每一个UIAbility实例,都对应一个最近任务列表中的任务,一个应用可以有一个或者多个UIability,而UIability里面也可以有一个或者多个页面)。

如一般的浏览器应用,通过一个UIAbility结合多页面的形式为用户提供服务。

页面间的跳转和数据传递

注意:页面通过DevEco进行创建,会自动注册

捕获.PNG
若是通过拷贝复制,或创建ArkTS空白文件而得到的页面,需要开发者去手动注册:

2a248bda8f66489a8046dd61d5b300f3.png

代码中所有的跳转页面路径必须按照注册的路径写,不能缩写

页面跳转

引入头文件:import router from '@ohos.router';

通过方法1:router.pushUrl()(新建一个页面,不会销毁原页面)

router.pushUrl({
    url: 'pages/Second',     //要跳转的目标页面所在路径
    params: {变量名:}  //由要跳转的原页面传递过去的参数
    
},router.RouterMode.Single)

(变量名是随意命名的,值是你要传递的那个值)

router.RouterMode.Singlerouter.RouterMode.Standard表示单例模式和多例模式。

在单例模式下,如果目标页面URL在页面栈已经存在相同的URL页面,离栈顶最近的相同的URL页面会被移动到栈顶,移动后的页面为新建页,原来的页面仍然存在栈中,页面栈中的元数数量不变,如果目标页面URL在页面栈中不存在相同的URL页面,按多例模式跳转,页面总个数+1。

通过方法2:router.replaceUrl()(新建一个页面,替换并销毁原页面)

注意:由于当前页面被替换并销毁,把以跳转回去后就无法再回退回来了

router.replaceUrl({
    url: 'pages/Second',    //要跳转的目标页面所在路径
    params:{变量名:}    //由要跳转的原页面传递过去的参数
},router.RouterMode.Single)

在单例式下,如果目标页面的URL在页面栈已经存在相同的URL页面,离栈顶最近同URL页面会被移动到栈顶,替换当前页面,并销毁被替换的当前页面,移动后的页面为新建页面,页面栈的元素数量会-1;如果目标页面的URL在页面栈中不存在相同的URL页面,按多例模式跳转,页面栈元素数量不变。

参数接收与页面返回

  • 通过调用router.getParams()方法来接收传递过来的自定义参数
import router from '@ohos.router';
 
@Entry
@Component
struct Second {
    @State src: string = router.getParams()['变量名'];
    
    // 页面内容
}
  • 通过调用router.back();和router.back({url: ‘pages/Index’});来返回页面。
// 返回上一页面
router.back();
 
// 返回到指定页面
router.back({url: 'pages/Index'});
  • 在页面返回时同样可以添加自定义参数:
router.back({
    url: 'pages/Index',
    params:{变量名:},
})
  • 原页面接收目标页面传回来的参数(通过生命周期函数onPageShow())
import router from '@ohos.router';
 
@Entry
@Component
struct Index {
    @State src: string = '';
 
    onPageShow() {   //通过该生命周期函数来接收传递过来的参数
    
        let  record:object= router.getParams()
        if(record)    //判断有没有返回值
        {
        
            this.src = record['变量名'] 
            as Record<string,string>       
        }
        
    }
 
    // 页面内容
}
页面参数params

params:{变量名:值} 变量名是随意命名的,值是你要传递的那个值

router.getParams() 返回的是一个无类型的对象(object类)

as Record<string,string> 将获得的数据中的每个键值对都转化成string : string

页面间的数据传输最好都是string类型的

UIAbility生命周期

22df8be42c8d4c779cb1c20ede10d0c7.png

UIAbility生命周期有四个:Create、Foreground(前台)、Background(后台)、Destroy

窗口管理器在UIAbility中管理UI界面功能的两个生命周期回调:WindowStageCreate、WindowStageDestroy

Create状态

在UIAbility实例创建时触发,系统会调用onCreate回调。可以在其中做相关的初始化操作。

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
 
export default class EntryAbility extends UIAbility {
 
    onCreate(want, launchParam) {
        // 应用初始化操作
        ...
    }
}

例如用户打开电池管理应用,在应用加载过程中,在UI页面可见之前,可以在onCreate回调中读取当前系统的电量情况,用于后续的UI页面展示。

WindowStageCreate

UIAbility实例创建完成后,在进入Foreground之前,系统会创建一个WindowStage

每一个UIAbility实例都对应持有一个WindowStage实例。

WindowStage为本地窗口管理器,用于管理窗口相关的内容,如界面相关的获焦/失焦、可见/不可见

可以在onWindowStageCreate回调中,设置UI页面加载、设置WindowStage的事件订阅

在onWindowStageCreate(windowStage)中通过loadContent接口设置应用要加载的页面。

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
 
export default class EntryAbility extends UIAbility {
 
    ...
    
    onWindowStageCreate(windowStage: window.WindowStage) {
        // 设置UI页面加载
        // 设置WindowStage事件订阅
        ...
        
        windowStage.loadContent('pages/Index',(err, data) => {
            ...
        })  //设置应用要加载的页面
    }
    
    ...
}

例如用户打开游戏应用,正在打游戏的时候,有一个消息通知,打开消息,消息会以弹窗的形式弹出在游戏应用的上方,此时,游戏应用就从获焦切换到了失焦状态,消息应用切换到了获焦状态。对于消息应用,在onWindowStageCreate回调中,会触发获焦的事件回调,可以进行设置消息应用的背景颜色、高亮等操作。

Foreground和Background状态

上面的状态分别是UIAbility切换至前台或者切换至后台时触发。它们分别对应的是onForeground回调onBackground回调。

onForeground回调:在UIAbility的UI页面可见之前,即UIAbility切换至前台时触。可以在其中申请系统需要的资源,或者重新申请在onBackground中释放的资源。

onBackground回调:在UIAbility的UI页面完全不可见之后,即UIAbility切换至后台时候触发。可以在onBackground回调中释放UI页面不可见时无用的资源,或者在此回调中执行较为耗时的操作,例如状态保存等。

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
 
export default class EntryAbility extends UIAbility {
 
    ...
    
    onForeground() {
        // 申请需要的资源
        ...
    }
 
    onBackground() {
        // 释放资源,或者执行较为耗时的任务
        ...
    }
}

例如用户打开地图应用查看当前地理位置的时候,假设地图应用已获得用户的定位权限授权。在UI页面显示之前,可以在onForeground回调中打开定位功能,从而获取到当前的位置信息。

当地图应用切换到后台状态,可以在onBackground回调中停止定位功能,以节省系统的资源消耗。

WindowStageDestroy

在UIAbility实例销毁之前,则会先进入onWindowStageDestroy回调,我们可以在该回调中释放UI页面资源。

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
 
export default class EntryAbility extends UIAbility {
 
    ...
    
    onWindowStageDestroy() {
        // 释放UI页面资源
        ...
    }
}

Destroy状态

在UIAbility销毁时触发。可以在onDestroy回调中进行系统资源的释放、数据的保存等操作。

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
 
export default class EntryAbility extends UIAbility {
    ...
 
    onDestroy() {
        // 系统资源的释放、数据的保存等
        ...
    }
}

UIAbility的启动模式

singleton(单实例模式)

singleton启动模式为单实例模式,也是默认情况下的启动模式。

每次调用startAbility() 方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。

singleton启动模式的开发使用,在module.json5文件中的“launchType”字段配置为“singleton”即可。

multiton与standard(多实例模式)

multiton与standard启动模式为多实例模式,每次调用startAbility() 方法时,都会在应用进程中创建一个新的该类型UIAbility实例。但是multiton启动模式会消除任务列表中的原来的同类型UIability实例,而standard启动模式不会,即在最近任务列表中可以看到有多个该类型的UIAbility实例

multiton启动模式的开发使用,在module.json5配置文件中的launchType字段配置为“multiton”即可。

specified(指定实例模式)

specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。

例如有两个UIAbility:EntryAbility和SpecifiedAbility,SpecifiedAbility配置为指定实例模式启动,需要从EntryAbility的页面中启动SpecifiedAbility。

在SpecifiedAbility中,将module.json5配置文件的launchType字段配置为specified。

在创建UIAbility实例之前,开发者可以为该实例指定一个唯一的字符串Key,这样在调用startAbility()方法时,应用就可以根据指定的Key来识别响应请求的UIAbility实例。在EntryAbility中,调用startAbility()方法时,可以在want参数中增加一个自定义参数,例如instanceKey,以此来区分不同的UIAbility实例。

specified (简述)

当应用的UIAbility实例已经被创建,并且配置为指定实例模式时,如果再次调用startAbility()方法启动该UIAbility实例,且AbilityStage的onAcceptWant()回调匹配到一个已创建的UIAbility实例,则系统会启动原来的UIAbility实例,并且不会重新创建一个新的UIAbility实例。此时,该UIAbility实例的onNewWant()回调会被触发,而不会触发onCreate()和onWindowStageCreate()生命周期回调。

specified (更简述)

UIAbility实例设置为specified后,每次准备创建新的UIAbility实例时,都需要传入一个唯一的关键字key,在正式创建前,会检查当前任务列表,有没有与现在关键字
相同的UIAbility实例(关键字与实例一一对应,且具有唯一性),有则直接调用现成的那个实例,不再创建新的实例,没有,则继续创建新的实例。

specified与singleton 模式区别

singleton模式下,在当前任务列表下,同一种类型的实例只能有一个,specified模式下同一个类型的实例(ability)可以有很多个(它们的关键字不同)。

specified启动模式详解与例程

ability初始化文件

捕获.PNG

EntryAbility.ts是名字叫EntryAbility的ability对应的初始化文件,onCreate(),onDestroy() 表示ability创建和消除时自动调用的函数,onWindowStageCreate()和onWindowStageDestroy() 表示窗口创建与消除时自动调用的函数,
onForeground()和onBackground() 表示ability 切换至前台或者切换至后台时自动调用的函数。

在同一模块下创建多个UIability

image.png
创建UIability

捕获.PNG

如上图两个ability-------EntryAbility和MyAbility

捕获.PNG

在对应的UIability的初始化文件中将初始生成页面由Index改为自己需要的页面(该UIability一被调用就会生成的第一个页面)。

当前UIability中拉起另一个UIability

  • 在当前的UIability中调用startAbility方法拉起另一个UIability(该实例已经创建好了,且就在任务列表中)。

let context:common.UIAbilityContext = getContext(this) as common.UIAbilityContext

//获得本UIability的上下文,方便后面调用startAbility方法。


//指定要调用的UIability的信息
let want: Want = {
  deviceId: '',   // deviceId为空表示本设备
  //(要调用的ability所在的设备名)
  
  bundleName: 'com.example.myapplication',
  //对应的要调用的ability所在的APP的唯一标识
  
  abilityName: 'SpecifiedAbility',
  //要调用的ability的名字
  
  moduleName: 'entry', // moduleName非必选,
  //( 要调用的ability所在的模块的名字)
  
  
  parameters: {
    instanceKey: this.getInstance()
    //getInstance():自定义方法,
    //用于生成要调用的ability的实例的唯一标识key
    
  },
}

//调用的UIability
this.context.startAbility(want)

  • 将要调用的UIability启动模式设置为specified。

捕获.PNG

  • 创建自定义的UIability的"舞台"(AbilityStage)------舞台是该模块所有ability共享通用的,详情见上面Stage模型。可以仿照UI ability的初始化文件格式书写(.ts)

    例程代码:

import AbilityStage from '@ohos.app.ability.AbilityStage'; 
import Want from '@ohos.app.ability.Want'; 

export default class MyAbilityStage extends AbilityStage { 
    onAcceptWant(want: Want): string {   
    //用于接收相互传递的want(方法名是固定的)
        if (want.abilityName === 'MyAbility')
        {
        //判断是不是指定的UIability
        
            return want.parameters.instanceKey
            //向系统传入该UIability实例对应的唯一关键字key
        }
        else
        {
            return " "
        }
     }
 }
  • 让自定义"舞台"(AbilityStage)生效-----在module.json5中添加关键字"srcEntry":“自定义舞台所在路径”

捕获.PNG

这样在UIability实例中启动另一个UIability的实例,且该UIability是specified启动模式的功能就完成了。

文章来源:https://blog.csdn.net/qq_56109699/article/details/135687175
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。