OpenHarmony 使用FA調(diào)PA能力實現(xiàn)JS消息訂閱功能
前言
目前JS UI框架提供的事件發(fā)布訂閱功能需要在API7版本上才能使用, 為滿足開發(fā)需求, 我們在JAVA側(cè)實現(xiàn)消息訂閱分發(fā)邏輯, 通過JS調(diào)JAVA能力將接口暴露給JS側(cè), 以實現(xiàn)消息訂閱發(fā)布能力。
效果展示
實現(xiàn)思路
1、定義消息數(shù)據(jù)
一個消息事件包含事件類型, 攜帶數(shù)據(jù), 我們先定義一個JavaBean對象表示消息數(shù)據(jù)。
class Event {
private String type;
private String data;
}
2、定義接口
消息數(shù)據(jù)模型有了, 可以開始定義接口了。
消息訂閱接口。
??key?
?用于表示訂閱者對象的標識. ??callback?
?是消息的回調(diào)接口, 我們希望訂閱者只接收到自己關心的事件, 所以還需要增加一個參數(shù)??subscribeEventTypes?
?表示關心的事件類型。
void subscribeEvent(key, subscribeEventTypes, callback)
取消訂閱接口。
有訂閱就會有取消, ??key?
?用于表示訂閱者對象的唯一標識。
void unSubscribeEvent(key)
發(fā)布消息接口。
發(fā)布消息接口, ??type?
?表示消息類型, ??data?
?表示攜帶的數(shù)據(jù)。
void publishEvent(type, data)
3、JAVA側(cè)邏輯
我們采用的是是PA調(diào)FA機制, 所以需要新建一個JAVA遠程服務Ability, 目前有??Server?
??和??Internal?
??兩種類型的服務Ability, 此處不需要考慮多進程和 生命周期問題, 所以這里使用??Internal?
?Ability。
(1)先創(chuàng)建一個類EventInternalAbility, 調(diào)用??setInternalAbilityHandler?
?接口實現(xiàn)JS側(cè)請求處理接口, 處理三種請求。
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: // 處理消息分發(fā)
publishEvent();
break;
}
return true;
}
}
(2) 處理訂閱消息請求, 我們需要在此函數(shù)下處理消息訂閱的事件類型和訂閱對象。
public class EventInternalAbility {
private void addObserver(MessageParcel data) {
JSON dataJson = new JSON(data.readString());
// 解析訂閱者的標識
String key = dataJson.get("key");
// 解析訂閱者關系的數(shù)據(jù)
List<String> subscribeEventTypes = dataJson.get("subscribeEventType");
// 添加訂閱者到map隊列中
observers.put(key, new EventObserver(subscribeEventTypes, data.readRemoteObject()));
}
}
(3) 處理取消訂閱消息請求, 此邏輯比較簡單, 將標識對應的訂閱對象移除即可。
observers.remove(key)
(4)處理消息分發(fā)請求, 我們需要在此函數(shù)下完成消息數(shù)據(jù)解析和消息分發(fā)處理。
public class EventInternalAbility {
private void publishEvent(MessageParcel data) {
// 解析數(shù)據(jù)
JSON dataJson = new JSON(data.readString());
Stirng eventType = dataJson.get("type");
Stirng eventData = dataJson.get("data");
// 分發(fā)消息
observers.forEach((key, eventObserver) -> {
if (eventObserver.getSubscribeEventType().contains(eventType)) {
eventObserver.handlenEvent(eventType, eventData);
}
});
}
}
(5)到此我們JAVA側(cè)的關鍵代碼已經(jīng)完成, 我們還需要在應用啟動入口添加啟動??EventInternalAbility?
?服務。
public class EventInternalAbility {
private static final EventInternalAbility INSTANCE = new EventInternalAbility();
// 添加啟動服務分發(fā)
public static void startServer() {
// 我們與已經(jīng)在構造函數(shù)下實現(xiàn)了JS側(cè)請求處理接口, 此處可為空
}
}
public class MyApplication extends AbilityPackage {
public void onInitialize() {
super.onInitialize();
// 在APP入口啟動服務
EventInternalAbility.startServer();
}
}
4. JS側(cè)邏輯
新建event-utils.js腳本文件, 實現(xiàn)上述定義的接口。
JS側(cè)的代碼比較簡單, 主要將入?yún)⒌臄?shù)據(jù)透傳給JAVA側(cè), 邏輯比較簡單, 此處不再一一講解。
將請求bundleName abilityName等參數(shù)抽為一個方法, 以減少重復代碼。
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)
}
發(fā)布消息:
publishEvent(type, data){
let params = getParams(Constants.PUBLISH_EVENT);
params.data = {
"type": type,
"data": data,
}
return FeatureAbility.callAbility(params)
}
總結(jié)
至此關鍵代碼邏輯已全部完成, 總體來說流程比較簡單, 主要使用JS UI框架提供的FA調(diào)PA能力, 將JAVA側(cè)的操作能力提供給JS側(cè)使用。