HarmonyOS 使用FA调PA能力实现JS消息订阅功能

Posted 开源基础软件社区官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS 使用FA调PA能力实现JS消息订阅功能相关的知识,希望对你有一定的参考价值。

作者: 余香鑫

前言

目前JS UI框架提供的事件发布订阅功能需要在API7版本上才能使用, 为满足开发需求, 我们在JAVA侧实现消息订阅分发逻辑, 通过JS调JAVA能力将接口暴露给JS侧, 以实现消息订阅发布能力

效果展示

实现思路

1. 定义消息数据

一个消息事件包含事件类型, 携带数据, 我们先定义一个JavaBean对象表示消息数据

class Event 
    private String type;
    private String data;

2. 定义接口

消息数据模型有了, 可以开始定义接口了.

  • 消息订阅接口,
    key用于表示订阅者对象的标识. callback是消息的回调接口, 我们希望订阅者只接收到自己关心的事件, 所以还需要增加一个参数subscribeEventTypes表示关心的事件类型

    void subscribeEvent(key, subscribeEventTypes, callback) 
  • 取消订阅接口
    有订阅就会有取消, key用于表示订阅者对象的唯一标识

    void unSubscribeEvent(key)
  • 发布消息接口
    发布消息接口, type表示消息类型, data表示携带的数据

    void publishEvent(type, data)

3. JAVA侧逻辑

我们采用的是是PA调FA机制, 所以需要新建一个JAVA远程服务Ability, 目前有ServerInternal两种类型的服务Ability, 此处不需要考虑多进程和 生命周期问题, 所以这里使用InternalAbility.

3.1 先创建一个类EventInternalAbility, 调用setInternalAbilityHandler接口实现JS侧请求处理接口, 处理三种请求

public class EventInternalAbility extends AceInternalAbility 
    private final ConcurrentHashMap<String, EventObserver> observers = new ConcurrentHashMap<>(10);

    private EventInternalAbility() 
        setInternalAbilityHandler(this::onRemoteRequest);
    

    private boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) 
        switch (code) 
            case SUBSCRIBE: // 处理订阅消息请求
                addObserver();
                break;
            case UNSUBSCRIBE: // 处理取消订阅消息请求
                removeObserver();
                break;
            case PUBLISH_EVENT: // 处理消息分发
                publishEvent();
                break;
        
        return true;
    

3.2 处理订阅消息请求, 我们需要在此函数下处理消息订阅的事件类型和订阅对象

public class EventInternalAbility 
    private void addObserver(MessageParcel data) 
        JSON dataJson = new JSON(data.readString());
        // 解析订阅者的标识
        String key = dataJson.get("key");
        // 解析订阅者关系的数据
        List<String> subscribeEventTypes = dataJson.get("subscribeEventType");
        // 添加订阅者到map队列中
        observers.put(key, new EventObserver(subscribeEventTypes, data.readRemoteObject()));
    

3.3 处理取消订阅消息请求, 此逻辑比较简单, 将标识对应的订阅对象移除即可

    observers.remove(key)

3.4 处理消息分发请求, 我们需要在此函数下完成消息数据解析和消息分发处理

public class EventInternalAbility 
    private void publishEvent(MessageParcel data) 
        // 解析数据
        JSON dataJson = new JSON(data.readString());
        Stirng eventType = dataJson.get("type");
        Stirng eventData = dataJson.get("data");
        // 分发消息
        observers.forEach((key, eventObserver) -> 
            if (eventObserver.getSubscribeEventType().contains(eventType)) 
                eventObserver.handlenEvent(eventType, eventData);
            
        );
    

3.5 到此我们JAVA侧的关键代码已经完成, 我们还需要在应用启动入口添加启动EventInternalAbility服务

public class EventInternalAbility 
    private static final EventInternalAbility INSTANCE = new EventInternalAbility();

    // 添加启动服务分发
    public static void startServer() 
        // 我们与已经在构造函数下实现了JS侧请求处理接口, 此处可为空
    


public class MyApplication extends AbilityPackage 
    @Override
    public void onInitialize() 
        super.onInitialize();
        // 在APP入口启动服务
        EventInternalAbility.startServer();
    

4. JS侧逻辑

新建event-utils.js脚本文件, 实现上述定义的接口;

JS侧的代码比较简单, 主要将入参的数据透传给JAVA侧, 逻辑比较简单, 此处不再一一讲解

  • 将请求bundleName abilityName等参数抽为一个方法, 以减少重复代码
const getParams = function (code) 
    return 
        messageCode: code,
        // todo 此处修改为你项目的bundleName和abilityName
        bundleName: com.chinasoftinc.event,
        abilityName: com.chinasoftinc.event.event.EventInternalAbility,
        abilityType: 1,
        syncOption: 0,
        data: code,
    ;
;
  • 订阅消息
 subscribeEvent(key, subscribeEventTypes, eventCallback) 
    let subInfoParams = getParams(Constants.SUBSCRIBE_INFO);
    subInfoParams.data = 
        "key": key,
        "subscribeEventTypes": subscribeEventTypes,
                
    FeatureAbility.subscribeAbilityEvent(params, eventCallback)
 
  • 取消订阅
   unsubscribeEvent(key)
      let params = getParams(Constants.UNSUBSCRIBE);
      params.data = 
        "key": key
      
      FeatureAbility.unsubscribeAbilityEvent(params)
   
  • 发布消息
   publishEvent(type, data)
      let params = getParams(Constants.PUBLISH_EVENT);
      params.data = 
        "type": type,
        "data": data,
      
      return  FeatureAbility.callAbility(params)   
   

总结

至此关键代码逻辑已全部完成, 总体来说流程比较简单, 主要使用JS UI框架提供的FA调PA能力, 将JAVA侧的操作能力提供给JS侧使用.
完整项目代码可以前往Gitee查看

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com/#bkwz

以上是关于HarmonyOS 使用FA调PA能力实现JS消息订阅功能的主要内容,如果未能解决你的问题,请参考以下文章

OpenHarmony之 eTS FA调用 eTS ServiceAbility

HarmonyOSArkUI 鸿蒙 ets怎么调用PA

#夏日挑战赛# HarmonyOS - 基于ArkUI(JS)实现打地鼠游戏

《鸿蒙理论知识02》HarmonyOS开发平台和工具

HarmonyOS - ArkUI(JS)实现数字记忆小游戏

Page 和Ability之间区别