Ability 是应用所具备能力的抽象,也是应用程序的重要组成部分。一个应用可以具备多种能力(即可以包含多个 Ability),HarmonyOS 支持应用以 Ability 为单位进行部署。Ability 可以分为 FA( Feature Ability )和 PA( Particle Ability )两种类型,每种类型为开发者提供了不同的模板,以便实现不同的业务功能。
FA 支持 Page Ability: Page 模板是FA唯一支持的模板,用于提供与用户交互的能力。一个 Page 实例可以包含一组相关页面,每个页面用一个 AbilitySlice 实例表示。
PA支持 Service Ability 和 Data Ability:
1、Service 模板:用于提供后台运行任务的能力。
2、Data 模板:用于对外部提供统一的数据访问抽象。
在配置文件(config.json)中注册 Ability 时,可以通过配置 Ability 元素中的“type”属性来指定 Ability 模板类型,示例如下。
其中,“type”的取值可以为“page”、“service”或“data”,分别代表 Page 模板、Service 模板、Data 模板。为了便于表述,后文中我们将基于 Page 模板、Service 模板、Data 模板实现的 Ability 分别简称为 Page、Service、Data。
{
"module": {
...
"abilities": [
{
...
"type": "page"
...
}
]
...
}
...
}
Page 模板(以下简称“Page”)是 FA 唯一支持的模板,用于提供与用户交互的能力。一个 Page 可以由一个或多个 AbilitySlice 构成,AbilitySlice 是指应用的单个页面及其控制逻辑的总和。
Page和AbilitySlice相当于android的Activity和fragment之间的关系一样。
鸿蒙系统支持不同 Page 之间的跳转,并可以指定跳转到目标 Page 中某个具体的 AbilitySlice。
AbilitySlice 路由配置:
Page 进入前台时界面默认只展示一个 AbilitySlice,
默认展示的 AbilitySlice 是通过setMainRoute()方法来指定的。如果需要更改默认展示的 AbilitySlice,可以通过addActionRoute()方法为此 AbilitySlice 配置一条路由规则。
public class MainAbility extends Ability {
//启动page的页面
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
//add设置路由
addActionRoute("action.news.list", NewsListSlice.class.getName());
addActionRoute("action.news.detail", NewsDetailSlice.class.getName());
}
}
addActionRoute() 方法中使用的动作命名,需要在应用配置文件(config.json)中注册:
{
"module": {
"abilities": [
{
"skills":[
{
"actions":[
"action.news.list",
"action.news.detail"
]
}
]
...
}
]
...
}
...
}
鸿蒙Intent的基本概念:
Intent 是对象之间传递信息的载体。例如,当一个 Ability 需要启动另一个 Ability 时,或者一个 AbilitySlice 需要导航到另一个 AbilitySlice 时,可以通过 Intent 指定启动的目标同时携带相关数据。Intent 的构成元素包括 Operation 与 Parameters,具体描述参见表1。
属性 | 子属性 | 描述 |
---|---|---|
Operation | Action | 表示动作,通常使用系统预置Action,应用也可以自定义Action。例如IntentConstants.ACTION_HOME表示返回桌面动作。 |
Entity | 表示类别,通常使用系统预置Entity,应用也可以自定义Entity。例如Intent.ENTITY_HOME表示在桌面显示图标。 | |
Uri | 表示Uri描述。如果在Intent中指定了Uri,则Intent将匹配指定的Uri信息,包括scheme, schemeSpecificPart, authority和path信息。 | |
Flags | 表示处理Intent的方式。例如Intent.FLAG_ABILITY_CONTINUATION标记在本地的一个Ability是否可以迁移到远端设备继续运行。 | |
BundleName | 表示包描述。如果在Intent中同时指定了BundleName和AbilityName,则Intent可以直接匹配到指定的Ability。 | |
AbilityName | 表示待启动的Ability名称。如果在Intent中同时指定了BundleName和AbilityName,则Intent可以直接匹配到指定的Ability。 | |
DeviceId | 表示运行指定Ability的设备ID。 | |
Parameters | - | Parameters是一种支持自定义的数据结构,开发者可以通过Parameters传递某些请求所需的额外信息。 |
当 Intent 用于发起请求时,根据指定元素的不同,分为两种类型:
同一Page内实现跳转:(present关键词)
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initComponents();
}
private void initComponents() {
Button button = (Button) findComponentById(ResourceTable.Id_button);
button.setClickedListener(listener -> present(new SecondAbilitySlice(), new Intent()));
}
跳转处理返回值:
1、用户从导航目标 AbilitySlice 返回时,能够获得其返回结果,则应当使用 presentForResult() 实现导航。系统将回调 onResult() 来接收和处理返回结果,开发者需要重写该方法。返回结果由导航目标 AbilitySlice 在其生命周期内通过 setResult() 进行设置。
private void queryWeather() {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction(Intent.ACTION_QUERY_WEATHER)
.build();
intent.setOperation(operation);
startAbilityForResult(intent, REQ_CODE_QUERY_WEATHER);
}
@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
switch (requestCode) {
case REQ_CODE_QUERY_WEATHER:
// Do something with result.
...
return;
default:
...
}
}
2、作为处理请求的对象,首先需要在配置文件中声明对外提供的能力,以便系统据此找到自身并作为候选的请求处理者。
{
"module": {
...
"abilities": [
{
...
"skills":[
{
"actions":[
"ability.intent.QUERY_WEATHER"
]
}
]
...
}
]
...
}
...
}
3、在 Ability 中配置路由以便支持以此 action 导航到对应的 AbilitySlice。
@Override
protected void onStart(Intent intent) {
...
addActionRoute(Intent.ACTION_QUERY_WEATHER, DemoSlice.class.getName());
...
}
4、在 Ability 中处理请求,并调用 setResult()方法暂存返回结果。
@Override
protected void onActive() {
...
Intent resultIntent = new Intent();
setResult(0, resultIntent);
...
}
注意:系统为每个 Page 维护了一个 AbilitySlice 实例的栈,每个进入前台的 AbilitySlice 实例均会入栈。当开发者在调用 present( )或 presentForResult() 时指定的 AbilitySlice 实例已经在栈中存在时,则栈中位于此实例之上的 AbilitySlice 均会出栈并终止其生命周期。前面的示例代码中,导航时指定的 AbilitySlice 实例均是新建的,即便重复执行此代码(此时作为导航目标的这些实例是同一个类),也不会导致任何 AbilitySlice 出栈。
不同 Page 之间跳转:
Intent intent = new Intent();
// 通过 Intent 中的 OperationBuilder 类构造 operation 对象,指定设备标识(空串表示当前设备)、应用包名、Ability 名称
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("com.demoapp")
.withAbilityName("com.demoapp.FooAbility")
.build();
// 把 operation 设置到 intent 中
intent.setOperation(operation);
startAbility(intent);