天天看点

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

作者: 余香鑫

前言

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

效果展示

HarmonyOS 使用FA调PA能力实现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, 目前有

Server

Internal

两种类型的服务Ability, 此处不需要考虑多进程和 生命周期问题, 所以这里使用

Internal

Ability.

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)   
   }
           

总结

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

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

完整项目代码可以前往Gitee查看

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

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

继续阅读