如上图所示,蓝色框内就是代表一个模块,一个工程下可以有n个模块,但只能有一个entry模块,即入口模块(核心),里面是该APP的主要功能。模块分为两种类型:Ability Module和Library Module模块,前者是能力模块,用于实现对应的页面和功能,后者是共享模块,里面的功能和已经创建的组件可以被其他模块共同调用,减少重复代码的书写。 所有模块在编译期统称为Bundle。每个模块都可以单独运行和测试
在代码运行时,每个模块都会搭建各自的"舞台",结构如上图,ArkUI Page :展示出来的UI界面,即与用户直接交互的地方,UIAbility是包含UI界面的应用组件,通过Window来将UI界面展示给用户,WindowStage是窗口的"舞台"。一个模块下可以有多个ability。
app.json5 文件里面是整个APP的全局配置信息,“bundleName” 是APP对应的唯一标识。"icon"对应APP在设置中的应用管理中的应用图标,"label"对应的是应用在设置中的应用管理中的名称。
module.json5 文件是对应模块特有的配置文件,“requestPermission” 用于向用户或系统申请权限,“name” 对应的是该模块名字,“type” 对应的是该模块的类型,
“description” 用于描述该模块内容,“mainElement” 当该模块下有多个ability(UIAbility或ExtensionAbility)时,用于标识入口ability,“deviceTypes” 该模块适用的设备,
“deliveryWithInstall” 该模块是否跟着APP一同被安装(有些模块可以设置为用户选择性安装),“pages” 是存放该模块下所有的页面路径的文件,“abilities” 是该模块下所有ability的对应属性,其中的"icon"和"label"对应的是APP在桌面上的应用图标和名称,"launchType"对应该ability的启动模式。
UIAbility就是包含有用户界面的一个组件-----即应用程序的入口,通过用户界面与用户进行交互。其也是系统调度的单元。
打开程序,进入用户界面,有3种方法:
1.点击桌面图标进入应用。
2.在一个应用中打开另一个应用。
3.从最近任务列表中切回应用(每一个UIAbility实例,都对应一个最近任务列表中的任务,一个应用可以有一个或者多个UIability,而UIability里面也可以有一个或者多个页面)。
如一般的浏览器应用,通过一个UIAbility结合多页面的形式为用户提供服务。
注意:页面通过DevEco进行创建,会自动注册:
若是通过拷贝复制,或创建ArkTS空白文件而得到的页面,需要开发者去手动注册:
代码中所有的跳转页面路径必须按照注册的路径写,不能缩写。
引入头文件:import router from '@ohos.router'
;
通过方法1:router.pushUrl()(新建一个页面,不会销毁原页面)
router.pushUrl({
url: 'pages/Second', //要跳转的目标页面所在路径
params: {变量名:值} //由要跳转的原页面传递过去的参数
},router.RouterMode.Single)
(变量名是随意命名的,值是你要传递的那个值)
router.RouterMode.Single和router.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({
url: 'pages/Index',
params:{变量名:值},
})
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:{变量名:值}
变量名是随意命名的,值是你要传递的那个值。
router.getParams()
返回的是一个无类型的对象(object类)
as Record<string,string>
将获得的数据中的每个键值对都转化成string : string
页面间的数据传输最好都是string类型的
UIAbility生命周期有四个:Create、Foreground(前台)、Background(后台)、Destroy
窗口管理器在UIAbility中管理UI界面功能的两个生命周期回调:WindowStageCreate、WindowStageDestroy
在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页面展示。
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回调中,会触发获焦的事件回调,可以进行设置消息应用的背景颜色、高亮等操作。
上面的状态分别是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回调中停止定位功能,以节省系统的资源消耗。
在UIAbility实例销毁之前,则会先进入onWindowStageDestroy回调,我们可以在该回调中释放UI页面资源。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
...
onWindowStageDestroy() {
// 释放UI页面资源
...
}
}
在UIAbility销毁时触发。可以在onDestroy回调中进行系统资源的释放、数据的保存等操作。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
...
onDestroy() {
// 系统资源的释放、数据的保存等
...
}
}
singleton启动模式为单实例模式,也是默认情况下的启动模式。
每次调用startAbility() 方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。
singleton启动模式的开发使用,在module.json5文件中的“launchType”字段配置为“singleton”即可。
multiton与standard启动模式为多实例模式,每次调用startAbility() 方法时,都会在应用进程中创建一个新的该类型UIAbility实例。但是multiton启动模式会消除任务列表中的原来的同类型UIability实例,而standard启动模式不会,即在最近任务列表中可以看到有多个该类型的UIAbility实例。
multiton启动模式的开发使用,在module.json5配置文件中的launchType字段配置为“multiton”即可。
specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。
例如有两个UIAbility:EntryAbility和SpecifiedAbility,SpecifiedAbility配置为指定实例模式启动,需要从EntryAbility的页面中启动SpecifiedAbility。
在SpecifiedAbility中,将module.json5配置文件的launchType字段配置为specified。
在创建UIAbility实例之前,开发者可以为该实例指定一个唯一的字符串Key,这样在调用startAbility()方法时,应用就可以根据指定的Key来识别响应请求的UIAbility实例。在EntryAbility中,调用startAbility()方法时,可以在want参数中增加一个自定义参数,例如instanceKey,以此来区分不同的UIAbility实例。
当应用的UIAbility实例已经被创建,并且配置为指定实例模式时,如果再次调用startAbility()方法启动该UIAbility实例,且AbilityStage的onAcceptWant()回调匹配到一个已创建的UIAbility实例,则系统会启动原来的UIAbility实例,并且不会重新创建一个新的UIAbility实例。此时,该UIAbility实例的onNewWant()回调会被触发,而不会触发onCreate()和onWindowStageCreate()生命周期回调。
UIAbility实例设置为specified后,每次准备创建新的UIAbility实例时,都需要传入一个唯一的关键字key,在正式创建前,会检查当前任务列表,有没有与现在关键字
相同的UIAbility实例(关键字与实例一一对应,且具有唯一性),有则直接调用现成的那个实例,不再创建新的实例,没有,则继续创建新的实例。
singleton模式下,在当前任务列表下,同一种类型的实例只能有一个,specified模式下同一个类型的实例(ability)可以有很多个(它们的关键字不同)。
EntryAbility.ts是名字叫EntryAbility的ability对应的初始化文件,onCreate(),onDestroy() 表示ability创建和消除时自动调用的函数,onWindowStageCreate()和onWindowStageDestroy() 表示窗口创建与消除时自动调用的函数,
onForeground()和onBackground() 表示ability 切换至前台或者切换至后台时自动调用的函数。
创建UIability
如上图两个ability-------EntryAbility和MyAbility
在对应的UIability的初始化文件中将初始生成页面由Index改为自己需要的页面(该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的"舞台"(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 " "
}
}
}
这样在UIability实例中启动另一个UIability的实例,且该UIability是specified启动模式的功能就完成了。