天天看點

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開發技術,歡迎投稿和訂閱,讓我們一起攜手前行共建鴻蒙生态。

繼續閱讀