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