作者:韩茹
鸿蒙巴士专栏作家
一、Page与AbilitySlice
Page
Page模板(以下简称“Page”)是FA唯一支持的模板,用于提供与用户交互的能力。一个Page可以由一个或多个AbilitySlice构成,AbilitySlice是指应用的单个页面及其控制逻辑的总和。
当一个Page由多个AbilitySlice共同构成时,这些AbilitySlice页面提供的业务能力应具有高度相关性。例如,新闻浏览功能可以通过一个Page来实现,其中包含了两个AbilitySlice:一个AbilitySlice用于展示新闻列表,另一个AbilitySlice用于展示新闻详情。Page和AbilitySlice的关系如下图所示。
AbilitySlice
这里的Slice,其实就是切片的意思。一组相关的AbilitySlice放在一个Page里。
AbilitySlice作为使用Page模板到能力的基本单元,提供了一种具有服务逻辑和UI显示载体的能力。
相比于桌面场景,移动场景下应用之间的交互更为频繁。通常,单个应用专注于某个方面的能力开发,当它需要其他能力辅助时,会调用其他应用提供的能力。例如,外卖应用提供了联系商家的业务功能入口,当用户在使用该功能时,会跳转到通话应用的拨号页面。与此类似,HarmonyOS支持不同Page之间的跳转,并可以指定跳转到目标Page中某个具体的AbilitySlice。
一个Ability可以由多个AbilitySlice组成。在Ability中,必须重写onStart(Intent)方法,通过setMainRoute(String)方法来指定默认的AbilitySlice。
而在AbilitySlice中,可以重写onStart(ohos.aafwk.content.Intent)来设置要显示的UI。通常,在AbilitySlice的整个生命周期中,UI只需要设置一次。
可以使用present(
ohos.aafwk.ability.AbilitySlice,ohos.aafwk.content.Intent)方法来呈现新的AbilitySlice,或者使用startAbility(ohos.aafwk.content.Intent)方法来启动新的AbilitySlice。
AbilitySlice必须始终托管在Ability中,并且其生命周期随Ability的生命周期而变化。AbilitySlice也有其独立的生命周期更改,这些更改发生在AbilitySlice的切换过程中。
我们可以为一个Ability指定多个action entry和一个默认的主entry。每个entry表示Ability可以提供的能力和UI。当一个Ability被启动时,系统将传递的Intent中的action字段与定义的entry进行匹配。如果找到指定的AbilitySlice,就会启动它,。如果传递的Intent中没有指定action字段,或者Intent中的action字段与定义的entry不匹配,则显示默认的AbilitySlice。
注册action后,其他的Ability也可以通过指定的action来打开AbilitySlice。
二、AbilitySlice路由配置
虽然一个Page可以包含多个AbilitySlice,但是Page进入前台时界面默认只展示一个AbilitySlice。默认展示的AbilitySlice是通过setMainRoute()方法来指定的。如果需要更改默认展示的AbilitySlice,可以通过addActionRoute()方法为此AbilitySlice配置一条路由规则。此时,当其他Page实例期望导航到此AbilitySlice时,可以在Intent中指定Action。addActionRoute() 方法中使用的动作命名,需要在应用配置文件(config.json)中注册。
setMainRoute()方法
setMainRoute()方法,可以调用此方法来设置该Ability的默认路由,即要呈现的AbilitySlice。此方法只能用于Page ability。注意:如果在onStart(ohos.aafwk.content.Intent),中未设置默认路由,则启动将失败。
我们创建一个Harmony项目,默认加载的是MainAbilitySlice,
package com.example.hanrupageability;
import com.example.hanrupageability.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
// 设置默认显示的AbilitySlice
super.setMainRoute(MainAbilitySlice.class.getName());
}
}
显示对应的ability_main.xml布局:
现在我们在layout目录下添加一个xml文件:ability_second.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:background_element="#2200ffff"
ohos:orientation="vertical">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="我是第二个AbilitySlice"
ohos:text_size="20fp"
/>
</DirectionalLayout>
然后在slice目录下新建一个对应的AbilitySlice:SecondAbilitySlice.JAVA
package com.example.hanrupageability.slice;
import com.example.hanrupageability.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
public class SecondAbilitySlice extends AbilitySlice{
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_second);
}
}
接下来我们可以通过setMainRoute()方法来设置显示SecondAbilitySlice:
package com.example.hanrupageability;
import com.example.hanrupageability.slice.MainAbilitySlice;
import com.example.hanrupageability.slice.SecondAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
// 设置默认显示的AbilitySlice
// super.setMainRoute(MainAbilitySlice.class.getName());
super.setMainRoute(SecondAbilitySlice.class.getName());
}
}
然后运行这个项目:
addActionRoute()方法
setMainRoute()方法与addActionRoute()方法的使用示例如下:
package com.example.hanrupageability;
import com.example.hanrupageability.slice.MainAbilitySlice;
import com.example.hanrupageability.slice.SecondAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
// 设置默认显示的AbilitySlice
super.setMainRoute(MainAbilitySlice.class.getName());
// super.setMainRoute(SecondAbilitySlice.class.getName());
// 配置路由规则显示
addActionRoute("action.test.second", SecondAbilitySlice.class.getName());
}
}
addActionRoute()方法中使用的动作命名,需要在应用配置文件(config.json)中注册:
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"action.test.second"
]
}
],
如图:
三、创建PageAbility
默认启动一个HarmonyOS应用App,跟根据config.json中的配置,先加载MainAbility。
{
"app": {
"bundleName": "com.example.hanrupageability",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.example.hanrupageability",
"name": ".MyApplication",
"mainAbility": "com.example.hanrupageability.MainAbility",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"action.test.second"
]
}
],
"orientation": "unspecified",
"name": "com.example.hanrupageability.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
}
]
}
}
在MainAbility中,根据设置的主路由,加载MainAbilitySlice:
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
}
在MainAbilitySlice中,根据setUIContent()设置要显示的xml布局文件,最终在我们的屏幕上显示ability_main.xml中的内容。
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
}
现在如果我们想默认加载自己写的Ability,我们来实现一下。
首先在java中新建一个Ability文件:MyAbility.java。
package com.example.hanrupageability;
import com.example.hanrupageability.slice.MyAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
public class MyAbility extends Ability {
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
// 设置主路由
super.setMainRoute(MyAbilitySlice.class.getName());
}
}
这里我们设置要加载对应MyAbilitySlice,接下来在slice包下,新建一个AbilitySlice文件:MyAbilitySlice.java:
package com.example.hanrupageability.slice;
import com.example.hanrupageability.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
public class MyAbilitySlice extends AbilitySlice {
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_my_layout);
}
}
然后我们在layout布局下新建一个xml布局文件:my_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="#33AA0000"
ohos:orientation="vertical">
<Text
ohos:height="match_parent"
ohos:width="match_parent"
ohos:text="新的入口"
ohos:text_size="30fp"
ohos:text_alignment="center"
/>
</DirectionalLayout>
这里我们复制到media里一个小图标t4.png:
最后,我们要在config.json中设置:
{
"app": {
"bundleName": "com.example.hanrupageability",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.example.hanrupageability",
"name": ".MyApplication",
"mainAbility": "com.example.hanrupageability.MainAbility",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"name": "com.example.hanrupageability.MyAbility",
"icon": "$media:t4",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
},
{
"orientation": "unspecified",
"name": "com.example.hanrupageability.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
}
]
}
}
然后启动项目,这个APP部署:
点进去,就有了新的入口:
我们也可以通过DevEco-Studio直接新建Ability,这样随着Ability的创建,会自动创建该Ability对应的AbilitySlice以及该AbilitSlice要加载的xml布局文件:
然后填入Ability的信息:
还有还有,会自动的配置config.json文件,超爽的: