harmonyos开发-Ability
Ability基本概念
Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。一个应用可以具备多种能力(即可包含多个Ability),harmonyos支持应用以Ability为单位进行部署。
Ability分为两种类型
- FA(Future Ability)
有界面
- PageAbility
用于和用户交互
,每个PAGE可以包含一组界面,每个PAGE用AbilitySlice
表示
- PageAbility
- PA(Particle Ability)
无界面
- Service
用提供后台任务能力
- Data
提供统一的数据访问抽象
- Service
AbilityType
- page
- service
- data
Page Ability基本概念
Page和AbilitySlice
page模板是FA唯一支持的模板,用户提供用户交互能力。一个Page可以由一个或多个AbilitySlice构成,AbilitySlice是指应用的单个页面及其控制逻辑的总和。
- Page
- AbilitySlice1
- AbilitySlice2
- AbilitySlice3
AbilitySlice之间的导航
实现一个AbilitySlice步骤
- 编写一个类
- 继承自AbilitySlice
- 重写
onStart
方法
package com.example.abilityslicedemo.slice;
import com.example.abilityslicedemo.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
public class NextSlice extends AbilitySlice {
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
// 加载页面信息
super.setUIContent(ResourceTable.Layout_ability_next);
}
}
ability_next.xml
<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
<Text
ohos:height="match_content"
ohos:width="match_content"
ohos:text="原来如此"
ohos:text_size="40vp"
ohos:top_padding="40px"/>
</DependentLayout>
切换页面
通过调用present方法来滑动页面,实现页面切换。
package com.example.abilityslicedemo.slice;
import com.example.abilityslicedemo.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
public class MainAbilitySlice extends AbilitySlice {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
Button button = findComponentById(ResourceTable.Id_button);
// 按钮点击事件
button.setClickedListener(obj -> {
// 滑动到自己创建的页面
present(new NextSlice(), new Intent());
});
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}
Page Ability生命周期
onStart
当系统首次创建Page实例时,触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后将进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
Button button = findComponentById(ResourceTable.Id_button);
button.setClickedListener(obj -> {
present(new NextSlice(), new Intent());
});
}
onActive
Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用onInactive()回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用onActive()回调。因此,开发者通常需要成对实现onActive()和onInactive(),并在onActive()中获取在onInactive()中被释放的资源。
onInactive
当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。
onBackground
如果Page不再对用户可见,系统将调用此回调通知开发者用户进行相应的资源释放,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。
onForeground
处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用onForeground()回调通知开发者,而后Page的生命周期状态回到INACTIVE状态。开发者应当在此回调中重新申请在onBackground()中释放的资源,最后Page的生命周期状态进一步回到ACTIVE状态,系统将通过onActive()回调通知开发者用户。
onStop
系统将要销毁Page时,将会触发此回调函数,通知用户进行系统资源的释放。销毁Page的可能原因包括以下几个方面:
-
用户通过系统管理能力关闭指定Page,例如使用任务管理器关闭Page。
-
用户行为触发Page的terminateAbility()方法调用,例如使用应用的退出功能。
-
配置变更导致系统暂时销毁Page并重建。
-
系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。
AbilitySlice之间的传值
我们知道Page由多个AbilitySlicez共同组成,每个AbilitySlice之间是可以相互传递值的,主要是通过Intnet
来传递值,可传递基本数据类型,和引用类型。
传递值
button.setClickedListener(obj->{
// 创建一个intent 对象用来存放信息
Intent params = new Intent();
params.setParam("name","jack");
params.setParam("age",22);
// 传递信息
present(new ResultSlice(),params);
});
接收值
package com.example.abilityslice.slice;
import com.example.abilityslice.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Text;
import java.util.Optional;
public class ResultSlice extends AbilitySlice {
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_value);
// if intent != null
Optional.ofNullable(intent).ifPresent(params->{
// 读取信息
String name = params.getStringParam("name");
int age = params.getIntParam("age", -1);
Text text = findComponentById(ResourceTable.Id_text_id);
text.setText(String.format("我叫%s,我%d岁了!",name,age));
});
}
}
PageSlice回传值
上面我们学会了Slice之间的信息传递,但是似乎发现是单方面的。那么我们下面来实现双向信息传递
操作流程
pageA
- 调用 presentForResult传递Intent对象
- 设置返回代码
- 重写 onResult方法
用来接受 setResult 方法传递回来的
- 反馈值
pageB
- setResult 方法 设置传递信息
- terminate 结束当前slice
pageA:传递信息
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
Button button = (Button) findComponentById(ResourceTable.Id_button);
button.setClickedListener(obj->{
Intent params = new Intent();
params.setParam("name","传递过去的信息");
// 设置要传递的信息和返回代码
presentForResult(new SecondAbilitySlice(),params,FORWARD_CODE);
});
pageB:设置回馈信息
public class SecondAbilitySlice extends AbilitySlice {
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_second);
Button button = (Button) findComponentById(ResourceTable.Id_second_button);
button.setClickedListener(obj->{
Intent result = new Intent();
result.setParam("token","米西米哇不拉几");
setResult(result);
terminate();
});
}
}
pageA:捕捉回馈信息
// 回馈事件
@Override
protected void onResult(int requestCode, Intent resultIntent) {
super.onResult(requestCode, resultIntent);
if (requestCode==FORWARD_CODE) {
Optional.ofNullable(resultIntent).ifPresent(result -> {
HiLog.info(new HiLogLabel(HiLog.LOG_APP,0x00201,"Result"),resultIntent.getStringParam("token"));
});
}
}
注意点
- setResult 来设置回馈信息
- terminate 来结束当前slice(page)
- 重写 onResult方法
Ability跳转指定Slice
Page之间是相互隔离的,不能直接通过present
或者presentForResult
来跳转。
如果有这样的需求则需要使用intent.OperationBuilder
来实现不同AbilityPage之间的跳转。
操作流程
- new Intent.OperationBuilder
- withDeviceId
设备ID 留空则是当前设备ID
- withBundleName
包名
- withAbilityName
要跳转的页面
- build()
构建成Operation对象
- withDeviceId
- intent.setOperation()
- startAbility(intent)
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
Button button = findComponentById(ResourceTable.Id_main_button);
button.setClickedListener(obj -> {
// 创建一个OperationBuilder
Operation build = new Intent.OperationBuilder()
// 设备ID 如果为空则为当前设备ID
.withDeviceId("")
// 包名
.withBundleName("com.example.sliceresult")
// 要跳转的页面
.withAbilityName("com.example.abilitytoslice.SecondAbility")
// 构建
.build();
Intent params = new Intent();
params.setOperation(build);
startAbility(params);
});
}
这种启动方法的好处
- 可以启动当前设备当前应用中其他PageAbility
- 可以启动当前项目中其他FA中的PageAbility
- 还可以启动其他设备中的PageAbility