harmonyos开发-Ability

后端 / 笔记 / 2021-10-24

harmonyos开发-Ability

Ability基本概念

​ Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。一个应用可以具备多种能力(即可包含多个Ability),harmonyos支持应用以Ability为单位进行部署。

​ Ability分为两种类型

  • FA(Future Ability) 有界面
    • PageAbility 用于和用户交互,每个PAGE可以包含一组界面,每个PAGE用AbilitySlice表示
  • PA(Particle Ability)无界面
    • Service 用提供后台任务能力
    • Data 提供统一的数据访问抽象

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生命周期

img

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对象
  • 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