本章介绍HarmonyOS的核心组件Ability的开发。
2.1 Ability概述
Ability翻译成中文就是“能力”的意思。在HarmonyOS中,Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。
2.1.1 单Ability应用和多Ability应用
一个应用可以具备多种能力,也就是说可以包含多个Ability。HarmonyOS支持应用以Ability为单位进行部署。
2.1.2 HarmonyOS应用模型
HarmonyOS应用模型的构成要素 1.应用组件 2.应用进程模型 3.应用线程模型 4.应用任务管理模型 5.应用配置文件 截至目前,在HarmonyOS中,Ability框架模型结构具有以下两种形态: 1.FA模型:API 8及更早版本的应用程序只能使用FA模型进行开发。 2.Stage模型:从API 9开始,Ability框架引入并支持使用Stage模型进行开发,也是目前HarmonyOS所推荐的开发方式。 FA模型和Stage模型的工程目录结构存在差异,Stage模型目前只支持使用ArkTS语言进行开发。本书示例也是采用Stage模型开发的。
2.2 FA模型介绍
FA(Feature Ability)模型是HarmonyOS早期版本(API 8及更早版本)开始支持的模型,目前已经不再主推。
2.2.1 FA模型中的Ability
FA模型中的Ability分为PageAbility、ServiceAbility、DataAbility、FormAbility四种类型。其中:
-
PageAbility是具备UI实现的Ability,是用户具体可见并可以交互的Ability实例。
-
ServiceAbility也是Ability的一种,但是没有UI,为其他Ability提供调用自定义的服务,在后台运行。
-
DataAbility也是没有UI的Ability,为其他Ability提供进行数据增、删、查的服务,在后台运行。
-
FormAbility是卡片Ability,是一种界面展示形式。
2.2.2 FA模型的生命周期
2.2.3 FA模型的进程线程模型
2.3 Stage模型介绍
Stage模型是HarmonyOS 3.1版本开始新增的模型,也是目前HarmonyOS主推且会长期演进的模型。在该模型中,由于提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的“舞台”,因此称这种应用模型为Stage模型。本节主要介绍以Stage模型为主的开发方式。
2.3.1 Stage模型的设计思想
Stage模型的设计基于如下3个出发点:
-
为复杂应用而设计
-
支持多设备和多窗口形态
-
平衡应用能力和系统管控成本
2.3.2 Stage模型的Ability生命周期
Ability的生命周期包括Create、Foreground、Background、Destroy四个状态,WindowStageCreate和WindowStageDestroy为窗口管理器(WindowStage)在Ability中管理UI界面功能的两个生命周期回调,从而实现Ability与窗口之间的弱耦合。
2.3.3 Stage模型的Ability启动模式
Ability的启动模式是指Ability实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了3种启动模式:
-
singleton(单实例模式)。
-
standard(标准实例模式)。
-
specified(指定实例模式)。
-
singleton启动模式
每次调用startAbility()方法时,如果应用进程中该类型的Ability实例已经存在,则复用系统中的Ability实例。系统中只存在唯一一个该Ability实例,即在最近任务列表中只存在一个该类型的Ability实例。此时,应用的Ability实例已创建,当再次调用startAbility()方法启动该Ability实例时,只会进入该Ability的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。 如果需要使用singleton启动模式,将module.json5配置文件中的"launchType"字段配置为"singleton''即可。
{
"module": {
...
"abilities": [
{
"launchType": "singleton",
...
}
]
}
}
-
standard启动模式
在standard启动模式下,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型的Ability实例,即在最近任务列表中可以看到有多个该类型的Ability实例。这种情况下,可以将Ability配置为standard。 如果需要使用standard启动模式,将module.json5配置文件中的"launchType"字段配置为"standard"即可。
-
specified启动模式
在specified启动模式下,在Ability实例创建之前,允许开发者为该实例创建一个唯一的字符串Key,创建的Ability实例绑定Key之后,后续每次调用startAbility()方法时,都会询问应用使用哪个Key对应的Ability实例来响应startAbility请求。运行时由Ability内部业务决定是否创建多个实例,如果匹配有该Ability实例的Key,则直接拉起与之绑定的Ability实例,否则创建一个新的Ability实例。 例如,用户在应用中重复打开同一个文档时,启动的均是最近任务列表中的同一个任务,以及在应用中重复新建文档时,启动的均是最近任务列表中的新任务。这种情况下,可以将Ability配置为specified。当再次调用startAbility()方法启动该Ability实例,且AbilityStage的onAcceptWant()回调匹配到一个已创建的Ability实例时,再次启动该Ability,只会进入该Ability的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。 如果需要使用specified启动模式,将module.json5配置文件的"launchType"字段配置为"specified"即可。
2.4 Ability内页面的跳转和数据传递
Ability的数据传递包括Ability内页面的跳转和数据传递、Ability间的数据跳转和数据传递。本节主要讲解Ability内页面的跳转和数据传递。
2.4.1 新建Ability内页面
初始化工程之后,会生成以下内容: 1.在src/main/ets/entryability目录下,初始会生成一个Ability文件EntryAbility.ts。可以在EntryAbility.ts文件中根据业务需要实现Ability的生命周期回调内容。 2.在src/main/ets/pages目录下,会生成一个Index页面。这也是基于Ability实现的应用的入口页面。可以在Index页面中根据业务需要实现入口页面的功能。
为了实现页面的跳转和数据传递,需要新建一个页面。在src/main/ets/pages目录下,可以通过右击New→Page来新建页面
在原有Index页面的基础上,新建一个名为Second的页面。
Second页面创建完成之后,会自动做两个动作。一个动作是在src/main/ets/pages目录下创建一个Second.ets文件。Second.ets文件内容如下:
@Entry
@Component
struct Second {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
另一个动作是将Second页面信息配置到src/main/resources/base/profile/main_pages.json文件中。main_pages.json文件内容如下:
{
"src": [
"pages/Index",
"pages/Second"
]
}
2.4.2 页面跳转及传参
页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页面URL找到目标页面,从而实现跳转。通过页面路由模块,可以使用不同的URL访问不同的页面,包括跳转到Ability内的指定页面,用Ability内的某个页面替换当前页面,返回上一个页面或指定的页面等。通过params来传递参数。
在使用页面路由之前,需要先导入router模块,代码如下:
//导入router模块
import router from '@ohos.router';
页面跳转有以下几种方式,根据需要选择一种方式跳转即可。
-
router.push()
通过调用router.push()方法,跳转到Ability内的指定页面。每调用一次router.push()方法,均会新建一个页面。默认情况下,页面栈数量会加1,页面栈支持的最大页面数量为32。 当页面栈数量较大或者超过32时,可以通过调用router.clear()方法清除页面栈中的所有历史页面,仅保留当前页面作为栈顶页面。 用法示例如下:
router.push({
url: 'pages/Second',
params: {
src: 'Index页面传来的数据',
}
})
2.router.push()加mode参数
router.push()方法新增了mode参数,可以将mode参数配置为router.RouterMode.Single单例模式和router.RouterMode.Standard标准模式。
在单实例模式下,如果目标页面在页面栈中已经存在同URL的页面,离栈顶最近的同URL的页面会被移动到栈顶,移动后的页面为新建页,原来的页面仍然保存在栈中,页面栈数量不变;如果目标页面在页面栈中不存在同URL的页面,那么按照标准模式跳转,页面栈数量会加1。
用法示例如下:
router.push({
url: 'pages/Second',
params: {
src: 'Index页面传来的数据',
}
}, router.RouterMode.Single)
3.router.replace()
通过调用router.replace()方法,跳转到Ability内的指定页面。即使用新的页面替换当前页面,并销毁被替换的当前页面,页面栈数量依然不变。
用法示例如下:
router.replace({
url: 'pages/Second',
params: {
src: 'Index页面传来的数据',
}
})
4.router.replace()加mode参数
router.replace()方法新增了mode参数,可以将mode参数配置为router.RouterMode.Single单实例模式和router.RouterMode.Standard标准模式。 在单实例模式下,如果目标页面在页面栈中已经存在同URL的页面,离栈顶最近的同RUL的页面会被移动到栈顶,替换当前页面,并销毁被替换的当前页面,移动后的页面为新建页,页面栈数量会减1;如果目标页面在页面栈中不存在同URL的页面,那么按照标准模式跳转,页面栈数量不变。
用法示例如下:
用法示例如下:
router.replace({
url: 'pages/Second',
params: {
src: 'Index页面传来的数据',
}
}, router.RouterMode.Single)
最后,在Index.ets文件中添加按钮以触发跳转。Index.ets代码如下:
//导入模块
import router from '@ohos.router';
import url from '@ohos.url';
@Entry
@Component
struct Index {
@State message: string = 'Index页面'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
//添加按钮,触发跳转
Button("跳转").fontSize(40).onClick(()=>{
router.pushUrl({
url:'pages/Second',
params:{
src:"Index页面传来的数据",
}})
})
}
.width('100%')
}
.height('100%')
}
}
2.4.3 参数接收
通过调用router.getParams()方法获取Index页面传递过来的自定义参数。
import router from '@ohos.router';
@Entry
@Component
struct Second {
@State src: string = router.getParams()?.['src'];
//页面刷新展示
...
}
可以调用router.back()方法返回上一个页面。
最终,完整的Second.ets代码如下:
//导入模块
import router from '@ohos.router';
@Entry
@Component
struct Second {
@State message: string = 'Second页面'
//获得其他页面跳转至当前时携带的参数名称为src的数据
@State src:string=router.getParams()?.['src']
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
//显示传参的内容
Text(this.src).fontSize(30)
//添加按钮,触发返回
Button('返回').fontSize(40).onClick(()=>{
router.back();
})
}
.width('100%')
}
.height('100%')
}
}
2.4.4 运行
在Index页面中,单击“跳转”按钮后,即可从Index页面跳转到Second页面,并在Second页面中接收参数和进行页面刷新展示。
当在Second页面单击“返回”按钮后,则会回到Index页面。
以上就是完整的页面跳转及传参,接收参数的过程。
2.5 小结
本章介绍了Ability的开发,内容包括Ability的概念、两种Ability模型。同时演示了如何实现Ability内页面的跳转和数据传递,以及如何实现启动Ability。
2.6 习题
1.判断题
(1)一个应用只能有一个Ability。( )
(2)创建的Empty Ability模板工程,初始会生成一个Ability文件。( )
(3)每调用一次router.push()方法,页面路由栈数量均会加1。( )
2.单选题
(1)API 9及以上,在router.push()方法中,默认的跳转页面使用的模式是哪一种?()
A. Standard B. Single C. Specified
(2)Ability启动模式需要在module.json5文件中配置哪个字段?( )
A. module B. skills C. launchType D. abilities
3.多选题
(1)API 9及以上,router.push()方法的mode参数可以配置为以下哪几种跳转页面使用
的模式?( )
A. Standard B. Single C. Specified
(2)Ability的生命周期有哪几个状态?( )
A. Create B. WindowStageCreate C. Foreground D. Background E. WindowStageDestroy F. Destroy
(3)Ability有哪几种启动模式?( )
A. Standard B. Singleton C. Specified