鸿蒙Ability
导语
在鸿蒙应用中在创建一个Page Ability(Feature Ability)时(Page Ability可以理解为安卓的Acitvity
),会生成两个类:“XxxAbility”和“XxxAbilitySlice”,和一个布局文件“ability_Xxx.xml”。
为什么创建Ability的时候,会有三个选项呢?还会自动生成AbilitySlice呢?
这就涉及到鸿蒙中一个很重要的概念——Ability
Ability概念
Ability是应用的重要组成部分,是应用所具备能力的抽象。一个应用可以具备多种能力(即可以包含多个Ability)。Ability可以分为FA(Feature Ability)和PA(Particle Ability)两种类型。
①Feature Ability
FA代表有界面的Ability,支持Page Ability模板(是FA唯一支持的模板),用于提供与用户交互的能力。
②Particle Ability
PA代表*面的Ability,支持Service Ability和Data Ability模板。
Service模板用于提供后台运行任务的能力,
Data模板用于对外部提供统一的数据访问抽象。
在配置文件config.json中注册Ability时,可以通过配置Ability元素中的“type”属性来指定Ability模板类型。
“type”的取值可以为“page”(代表Page模板)、“service”(代表Service模板)或“data”(代表Data模板)。
Feature Ability
Page与AbilitySlice
Page模板是Feature Ability唯一支持的模板。一个Page实例可以包含一组相关页面,每个页面用一个AbilitySlice实例表示。
在Feature Ability中,有一个很重要的概念就是AbilitySlice,一个Feature Ability可以由一个或多个AbilitySlice构成。
AbilitySlice是Feature Ability的组成单元,是指应用的单个可视化界面及其交互逻辑的总和。一个Feature Ability可以包含一组业务关系密切的可视化界面,每一个可视化界面对应一个AbilitySlice。可以这么说:Feature Ability本质上就是一个页面,可以称为Page Ability(后文将称Feature Ability为Page Ability),这里的Page可以理解为Android中的Activity,Abilityslice可以理解为Android中的Layout。
Ability可以有界面(如Feature Ability),也可以没有界面(如Particle Ability)
有界面要显示时,在Ability中,通过setMainRoute关联要显示的AbilitySlice(XxxAbility通过SetMainRoute关联XxxAbilitySlice
)
设置布局文件、处理业务逻辑的代码写在AbilitySlice中(和布局文件ability_xxx.xml关联的是XxxAbilitySlice
)
在Page Ability中用代码编写界面
public class CodeWritePageAbilitySlice extends AbilitySlice {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
//super.setUIContent(ResourceTable.Layout_ability_code_write_page);
// 使用代码生成 UI 布局与组件
// 声明布局 创建相对布局, 传入当前界面 Ability 对象
DirectionalLayout directionalLayout = new DirectionalLayout(this);
// 设置布局大小
directionalLayout.setWidth(MATCH_PARENT);
directionalLayout.setHeight(MATCH_PARENT);
// // 创建布局配置对象DirectionalLayout.LayoutConfig
// // 构造函数中传入宽高设置
// DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(
// DirectionalLayout.LayoutConfig.MATCH_PARENT,
// DirectionalLayout.LayoutConfig.MATCH_PARENT);
// // 将布局配置对象设置给布局对象
// directionalLayout.setLayoutConfig(layoutConfig);
// 设置水平方向
directionalLayout.setOrientation(Component.HORIZONTAL);
// 设置布局背景为淡蓝色
// 创建背景元素
ShapeElement shapeElement = new ShapeElement();
// 设置淡蓝色
shapeElement.setRgbColor(new RgbColor(187, 255, 255));
// 设置页面背景颜色(将背景设置给布局)
directionalLayout.setBackground(shapeElement);
// 创建一个Text文本组件
Text text = new Text(this);
// 设置文本的布局
// 创建布局配置对象DependentLayout.LayoutConfig
// 在构造函数中传入宽高设置,这里设置成宽800、高自适应
DependentLayout.LayoutConfig textLayoutConfig = new DependentLayout.LayoutConfig(
800, DependentLayout.LayoutConfig.MATCH_CONTENT);
//设置margin
textLayoutConfig.setMargins(100, 100, 100, 100);
// 将布局配置对象设置给布局对象(为组件添加对应布局的布局属性)
text.setLayoutConfig(textLayoutConfig);
// 设置text布局背景为淡紫色
// 创建背景元素
ShapeElement shapeElementText = new ShapeElement();
// 设置淡紫色
shapeElementText.setRgbColor(new RgbColor(230, 230, 250));
// 将背景设置给布局 设置页面背景颜色
text.setBackground(shapeElementText);
// 设置显示的文本
text.setText("Hi there");
// 设置文字颜色
text.setTextColor(Color.BLACK);
//text.setTextColor(new Color(0xFF258293));
// 设置文字大小
text.setTextSize(100);
// 设置对齐方式 , 居中
text.setTextAlignment(TextAlignment.CENTER);
// 将组件添加到布局中
directionalLayout.addComponent(text);
//将布局作为根布局添加到视图树中
super.setUIContent(directionalLayout);
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}
生命周期
Page Ability生命周期
官方文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ability-page-lifecycle-0000000000029840#ZH-CN_TOPIC_0000001083455837__fig3655123011010
public class LifeCycleAbility extends Ability {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");
@Override
public void onStart(Intent intent) {
//当系统首次创建Page实例时,触发该回调,该回调在其生命周期过程中仅触发一次。
//Page在该逻辑后将进入INACTIVE(非激活状态)状态。
//开发者必须重写该方法,并在此使用setMainRoute配置默认展示的AbilitySlice。
super.onStart(intent);
super.setMainRoute(LifeCycleAbilitySlice.class.getName());
HiLog.info(LABEL, "LifeCycleAbility.onStart");
}
@Override
protected void onActive() {
//该状态是应用与用户交互的状态
// (进入前台时触发)
super.onActive();
HiLog.info(LABEL, "LifeCycleAbility.onActive");
}
@Override
protected void onInactive() {
//开发者应该在此回调中实现Page失去焦点时应表现的恰当行为,如释放资源
//(失去焦点时触发)
super.onInactive();
HiLog.info(LABEL, "LifeCycleAbility.onInactive");
}
@Override
protected void onBackground() {
//开发者应该在此回调中释放Page不可见时无用的资源
//或在此回调中执行较为耗时的状态保存操作
//(不可见时触发)
super.onBackground();
HiLog.info(LABEL, "LifeCycleAbility.onBackground");
}
@Override
protected void onForeground(Intent intent) {
//开发者应当在此回调中重新申请在onBackground()中释放的资源
//(重新进入可见状态时触发)
super.onForeground(intent);
HiLog.info(LABEL, "LifeCycleAbility.onForeground");
}
@Override
protected void onStop() {
//系统将要销毁Page时,将会触发此回调函数,通知用户进行系统资源的释放
//(销毁Ability时触发)
super.onStop();
HiLog.info(LABEL, "LifeCycleAbility.onStop");
}
}
注意
onStart()在整个生命周期过程中仅触发一次,而onActive()在每一次从后台回到前台的时候都会被调用,所以在开发中,把只需要加载一次的资源放在onStart()中,把要实时变更的资源放在onActive()中。
开发者通常需要成对实现onActive()和onInactive(),在onActive()中获取在onInactive()中被释放的资源。
AbilitySlice生命周期
AbilitySlice作为Page Ability的组成单元,其生命周期是依托于其所属Page Ability生命周期的。
AbilitySlice和Page Ability具有相同的生命周期状态和同名的回调,当Page Ability生命周期发生变化时,它的AbilitySlice也会发生相同的生命周期变化。
此外,AbilitySlice还具有独立于Page Ability的生命周期变化,这发生在同一Page Ability中的AbilitySlice之间导航时,此时Page Ability的生命周期状态不会改变,AbilitySlice生命周期回调与Page Ability的相应回调类似。当Page Ability被系统销毁时,其所有已实例化的AbilitySlice将联动销毁,而不仅是处于前台的AbilitySlice。
public class LifeCycleAbilitySlice extends AbilitySlice {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");
@Override
public void onStart(Intent intent) {
super.onStart(intent);
//由于AbilitySlice承载具体的页面,开发者必须重写AbilitySlice的onStart()回调,并在此方法中通过setUIContent()方法设置页面
super.setUIContent(ResourceTable.Layout_ability_life_cycle);
HiLog.info(LABEL, "LifeCycleAbilitySlice.onStart");
}
@Override
public void onActive() {
super.onActive();
HiLog.info(LABEL, "LifeCycleAbilitySlice.onActive");
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
HiLog.info(LABEL, "LifeCycleAbilitySlice.onForeground");
}
@Override
protected void onBackground() {
super.onBackground();
HiLog.info(LABEL, "LifeCycleAbilitySlice.onBackground");
}
@Override
protected void onInactive() {
super.onInactive();
HiLog.info(LABEL, "LifeCycleAbilitySlice.onInactive");
}
@Override
protected void onStop() {
super.onStop();
HiLog.info(LABEL, "LifeCycleAbilitySlice.onStop");
}
}
生命周期示例
生命周期示例之同一Page跳转
在LifeCycleAbilitySlice的onStart()中增加按钮跳转到LifeCycleSecondAbilitySlice
//生命周期示例之同一Page跳转
Button button = (Button) findComponentById(ResourceTable.Id_button);
// 为按钮设置点击回调
button.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
present(new LifeCycleSecondAbilitySlice(), new Intent());
}
});
LifeCycleSecondAbilitySlice.java的代码如下:
/**
* 生命周期测试AbilitySlice
*
* @author 舒小羽
* @date 2021/4/15 0015
*/
public class LifeCycleSecondAbilitySlice extends AbilitySlice {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onStart");
// 声明布局 创建相对布局, 传入当前界面 Ability 对象
DependentLayout dependentLayout = new DependentLayout(this);
// 创建布局配置对象DependentLayout.LayoutConfig
// 构造函数中传入宽高设置
DependentLayout.LayoutConfig layoutConfig = new DependentLayout.LayoutConfig(
DependentLayout.LayoutConfig.MATCH_PARENT,
DependentLayout.LayoutConfig.MATCH_PARENT);
// 将布局配置对象设置给布局对象
dependentLayout.setLayoutConfig(layoutConfig);
// 设置布局背景为粉红色
// 创建背景元素
ShapeElement shapeElement = new ShapeElement();
// 设置粉红色
shapeElement.setRgbColor(new RgbColor(255, 130, 171));
// 设置页面背景颜色(将背景设置给布局)
dependentLayout.setBackground(shapeElement);
// 创建一个Text文本组件
Text text = new Text(this);
// 设置文本的布局
text.setWidth(MATCH_CONTENT);
// 设置显示的文本
text.setText("同一个Page的跳转");
// 设置文字颜色
text.setTextColor(Color.BLACK);
// 设置文字大小
text.setTextSize(100);
// 将组件添加到布局中
dependentLayout.addComponent(text);
//将布局作为根布局添加到视图树中
super.setUIContent(dependentLayout);
}
@Override
public void onActive() {
super.onActive();
HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onActive");
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onForeground");
}
@Override
protected void onBackground() {
super.onBackground();
HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onBackground");
}
@Override
protected void onInactive() {
super.onInactive();
HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onInactive");
}
@Override
protected void onStop() {
super.onStop();
HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onStop");
}
}
运行代码。。。。。。。。。。。。。。。。。。。。。。。。。
首先启动LifeCycleAbility的是LifeCycleAbilitySlice,生命周期的调用顺序为:
LifeCycleAbility.onStart–>LifeCycleAbilitySlice.onStart–>LifeCycleAbility.onActive–>LifeCycleAbilitySlice.onActive可以看出AbilitySlice作为Page Ability的组成单元,其生命周期是依托于其所属Page Ability生命周期的。 AbilitySlice和Page Ability具有相同的生命周期状态和同名的回调,当Page Ability生命周期发生变化时,它的AbilitySlice也会发生相同的生命周期变化。
resultValue: LifeCycleAbility.onStart
resultValue: LifeCycleAbilitySlice.onStart
resultValue: LifeCycleAbility.onActive
resultValue: LifeCycleAbilitySlice.onActive
当点击LifeCycleAbilitySlice中的按钮跳转到LifeCycleAbility的LifeCycleSecondAbilitySlice,生命周期的调用顺序为:
LifeCycleAbilitySlice.onInactive–>LifeCycleSecondAbilitySlice.onStart–>LifeCycleSecondAbilitySlice.onActive–>LifeCycleAbilitySlice.onBackground
resultValue: LifeCycleAbilitySlice.onInactive
resultValue: LifeCycleSecondAbilitySlice.onStart
resultValue: LifeCycleSecondAbilitySlice.onActive
resultValue: LifeCycleAbilitySlice.onBackground
当点击返回按钮,从LifeCycleSecondAbilitySlice返回到LifeCycleAbilitySlice,生命周期的调用顺序为:
LifeCycleSecondAbilitySlice.onInactive–>LifeCycleAbilitySlice.onForeground–>LifeCycleAbilitySlice.onActive–>LifeCycleSecondAbilitySlice.onBackground–>LifeCycleSecondAbilitySlice.onStop
resultValue: LifeCycleSecondAbilitySlice.onInactive
resultValue: LifeCycleAbilitySlice.onForeground
resultValue: LifeCycleAbilitySlice.onActive
resultValue: LifeCycleSecondAbilitySlice.onBackground
resultValue: LifeCycleSecondAbilitySlice.onStop
同一Page中的AbilitySlice之间导航,Page的生命周期状态不会改变。在这个流程中,MainAbility始终处于活跃状态。
当点击手机Home键的时候,生命周期的调用顺序为:
LifeCycleAbility.onInactive–>LifeCycleAbilitySlice.onInactive–>LifeCycleAbility.onBackground–>LifeCycleAbilitySlice.onBackground
resultValue: LifeCycleAbility.onInactive
resultValue: LifeCycleAbilitySlice.onInactive
resultValue: LifeCycleAbility.onBackground
resultValue: LifeCycleAbilitySlice.onBackground
生命周期示例之不同Page跳转
在LifeCycleAbilitySlice的onStart()中增加按钮跳转到LifeCycleDifferentPageAbility
//生命周期示例之不同Page跳转
Button button1 = (Button) findComponentById(ResourceTable.Id_button1);
// 为按钮设置点击回调
button1.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("org.example.harmonypageabilitydemo")
.withAbilityName(".LifeCycleDifferentPageAbility")
.build();
intent.setOperation(operation);
startAbility(intent);
}
});
LifeCycleDifferentPageAbility.java的代码如下:
public class LifeCycleDifferentPageAbility extends Ability {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(LifeCycleDifferentPageAbilitySlice.class.getName());
HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onStart");
}
@Override
protected void onActive() {
super.onActive();
HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onActive");
}
@Override
protected void onInactive() {
super.onInactive();
HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onInactive");
}
@Override
protected void onBackground() {
super.onBackground();
HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onBackground");
}
@Override
protected void onForeground(Intent intent) {
super.onForeground(intent);
HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onForeground");
}
@Override
protected void onStop() {
super.onStop();
HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onStop");
}
}
LifeCycleDifferentPageAbilitySlice.java的代码如下:
public class LifeCycleDifferentPageAbilitySlice extends AbilitySlice {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_life_cycle_different_page);
HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onStart");
}
@Override
public void onActive() {
super.onActive();
HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onActive");
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onForeground");
}
@Override
protected void onBackground() {
super.onBackground();
HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onBackground");
}
@Override
protected void onInactive() {
super.onInactive();
HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onInactive");
}
@Override
protected void onStop() {
super.onStop();
HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onStop");
}
}
运行代码。。。。。。。。。。。。。。。。。。。。。。。。。
可以看见,从LifeCycleAbility跳转到LifeCycleDifferentPageAbility,
LifeCycleAbility和LifeCycleAbilitySlice首先都失去焦点,调用了onInactive,接着,LifeCycleDifferentPageAbility与LifeCycleDifferentPageAbilitySlice启动,调用了onStart,然后一起进入了前台,调用了onActive,最后,LifeCycleAbility与LifeCycleAbilitySlice都不可见了,调用了onBackground。
resultValue: LifeCycleAbility.onInactive
resultValue: LifeCycleAbilitySlice.onInactive
resultValue: LifeCycleDifferentPageAbility.onStart
resultValue: LifeCycleDifferentPageAbilitySlice.onStart
resultValue: LifeCycleDifferentPageAbility.onActive
resultValue: LifeCycleDifferentPageAbilitySlice.onActive
resultValue: LifeCycleAbility.onBackground
resultValue: LifeCycleAbilitySlice.onBackground
当点击了返回按钮后
从LifeCycleDifferentPageAbility回到LifeCycleAbility
先是LifeCycleDifferentPageAbility与LifeCycleDifferentPageAbilitySlice失去焦点触发onInactive,其次是LifeCycleAbility与LifeCycleAbilitySlice重新进入可见触发onForeground,再是LifeCycleAbility与LifeCycleAbilitySlice进入前台触发onActive,然后是LifeCycleDifferentPageAbility与LifeCycleDifferentPageAbilitySlice不可见触发onBackground,最后LifeCycleDifferentPageAbility与LifeCycleDifferentPageAbilitySlice销毁触发onStop。
resultValue: LifeCycleDifferentPageAbility.onInactive
resultValue: LifeCycleDifferentPageAbilitySlice.onInactive
resultValue: LifeCycleAbility.onForeground
resultValue: LifeCycleAbilitySlice.onForeground
resultValue: LifeCycleAbility.onActive
resultValue: LifeCycleAbilitySlice.onActive
resultValue: LifeCycleDifferentPageAbility.onBackground
resultValue: LifeCycleDifferentPageAbilitySlice.onBackground
resultValue: LifeCycleDifferentPageAbility.onStop
resultValue: LifeCycleDifferentPageAbilitySlice.onStop
AbilitySlice间的导航
同一Page内导航(同一Page页面的AbilitySlice间的导航)
不同Page间导航(不同Page页面的AbilitySlice间的导航(跨Pgae页面))
AbilitySlice路由配置
虽然一个Page Ability可以由一个或多个AbilitySlice构成,但是Page进入前台时界面默认只展示一个AbilitySlice。默认展示的AbilitySlice是通过setMainRoute()方法来指定的。
如果需要更改默认展示的AbilitySlice,可以通过addActionRoute() 方法为此AbilitySlice配置一条路由规则,当其他Page实例期望导航到此AbilitySlice时,可以在Intent中指定Action。配置了新的路由规则后,需要在配置文件中将其声明,否则会找不到。
setMainRoute()方法与addActionRoute()方法使用示例如下:
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
//设置默认展示的AbilitySlice
super.setMainRoute(MainAbilitySlice.class.getName());
//set the action route
//设置路由规则,应用于不同page的导航
addActionRoute("action.second", SecondAbilitySlice.class.getName());
}
}
就是说,"action.second"这个action值匹配的是SecondAbilitySlice这个slice,当需要跳转到SecondAbilitySlice这个slice的时候,通过指定"action.second"这个action值跳转到slice。
在配置文件中声明配置的新的路由规则示例如下:
同一Page内导航
跳转不携带数据
Button button = (Button) findComponentById(ResourceTable.Id_button);
// 为按钮设置点击回调
button.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
//第一种导航方式,跳转到同一page内不携带数据
//参数1:需要导航去的页面,参数2:Intent对象
present(new SamePageSlice(), new Intent());
}
});
跳转并携带数据
Button button2 = (Button) findComponentById(ResourceTable.Id_button2);
// 为按钮设置点击回调
button2.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
//第二种导航方式,跳转到同一page内并携带数据
Intent intent1 = new Intent();
intent1.setParam("name", "yu");
present(new SamePageSlice(), intent1);
}
});
接收携带的数据(如果携带了参数跳转,如何获取到传递的参数呢?)
Intent作为处理请求的对象,会在相应的回调方法中接收请求方传递的Intent对象,导航的目标可以在其onStart()回调的参数中获得Intent对象。
需要跳转过去的Slice的onStart()方法的参数就是一个Intent,因此可以直接通过此Intent去获取传递过去的参数。
//第二种导航方式,跳转到同一page内并携带数据
//接收携带的数据
Text text = (Text) findComponentById(ResourceTable.Id_text);
if (intent != null) {
text.setText("接收到的数据name=" + intent.getStringParam("name"));
}
跳转并返回数据
如果开发者希望在用户从导航目标AbilitySlice返回时,能够获得其返回结果,则应当使用presentForResult()实现导航。用户从导航目标AbilitySlice返回时,系统将回调onResult()来接收和处理返回结果,开发者需要重写该方法。
text = (Text) findComponentById(ResourceTable.Id_text);
Button button3 = (Button) findComponentById(ResourceTable.Id_button3);
// 为按钮设置点击回调
button3.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
//第三种导航方式,跳转到同一page内并返回数据
//参数1:需要导航去的页面,参数2:Intent对象,参数3:请求码
presentForResult(new SamePageSlice(), new Intent(), 0);
}
});
//第三种导航方式,跳转到同一page内并返回数据
//接收返回的数据
@Override
protected void onResult(int requestCode, Intent resultIntent) {
super.onResult(requestCode, resultIntent);
//接收requestCode == 0的返回的数据
if (requestCode == 0) {
int id = resultIntent.getIntParam("ID", -1);//-1为默认值,如果没有传回id的话
text.setText("回传的数据 id=" + id);
}
}
返回数据
//第三种导航方式,跳转到同一page内并返回数据
//返回数据(按返回键时有效)
Intent intent1 = new Intent();
intent1.setParam("ID", 123);
setResult(intent1);
//自动返回上一页
//terminate();
注:
第二种和第三种导航方式可以结合成跳转到同一page内携带数据并返回数据
不同Page间导航
不同Page中的AbilitySlice相互不可见,所以不能通过present()和presentForResult()方法直接导航。AbilitySlice作为Page的内部单元,以Action的形式向外暴露,因此可以通过配置Intent的Action导航到目标AbilitySlice。
Page间的导航可以使用startAbility()或startAbilityForResult()方法,获得返回结果的回调为onAbilityResult()。在Ability中调用setResult()可以设置返回结果。
根据Ability的全称启动应用
Button button5 = (Button) findComponentById(ResourceTable.Id_button5);
button5.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
//根据Ability的全称启动应用,通过Intent来跳转
Intent intent1 = new Intent();
//指定待启动FA的bundleName和abilityName
//通过Intent中的OperationBuilder类构造operation对象
//指定设备标识(空串表示当前设备)、应用包名、Ability名称
Operation operation = new Intent.OperationBuilder()
//设备id(空串表示当前设备)
.withDeviceId("")
//应用的包名 表示包描述。
//如果在Intent中同时指定了BundleName和AbilityName,则Intent可以直接匹配到指定的Ability。
//如果未同时指定BundleName和AbilityName,则根据Operation中的其他属性来启动应用。
.withBundleName("org.example.harmonypageabilitydemo")
//跳转目标的路径名 通常是包名+类名 或者 .+类名
//表示待启动的Ability名称。
.withAbilityName("org.example.harmonypageabilitydemo.SecondAbility")
//.withAbilityName(".SecondAbility")
.build();
//设置操作方式 把operation设置到intent中
intent1.setOperation(operation);
//通过AbilitySlice的startAbility接口实现启动另一个页面
startAbility(intent1);
//导航的目标Ability可以在其onStart()回调的参数中获得Intent对象
}
});
根据Operation的其他属性启动应用
也就是指定另一个page中的AbilitySlice的action值
withAction的值"action.second"已经在前节的AbilitySlice路由配置用配置过了。
Button button4 = (Button) findComponentById(ResourceTable.Id_button4);
button4.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
Intent intent1 = new Intent();
Operation operation = new Intent.OperationBuilder()
//指定另一个page中的AbilitySlice的action值
.withAction("action.second")
.build();
intent1.setOperation(operation);
startAbility(intent1);
}
});
Intent
提到页面跳转,就不得不提Intent
官方文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ability-intent-0000000000038799
Intent是对象之间传递信息的载体。例如,当一个Ability需要启动另一个Ability时,或者一个AbilitySlice需要导航到另一个AbilitySlice时,可以通过Intent指定启动的目标同时携带相关数据。