文章目录
- 目前JS UI框架提供的事件发布订阅功能需要在API7版本上才能使用, 为满足开发需求, 我们在JAVA侧实现消息订阅分发逻辑, 通过JS调JAVA能力将接口暴露给JS侧, 以实现消息订阅发布能力。
-
- 一个消息事件包含事件类型, 携带数据, 我们先定义一个JavaBean对象表示消息数据。 class Event { private String type; private String data;}
- 消息数据模型有了, 可以开始定义接口了。 消息订阅接口。 key用于表示订阅者对象的标识. callback是消息的回调接口, 我们希望订阅者只接收到自己关心的事件, 所以还需要增加一个参数subscribeEventTypes表示关心的事件类型。 void subscribeEvent(key, subscribeEventTypes, callback) 取消订阅接口。 有订阅就会有取消, key用于表示订阅者对象的唯一标识。 void unSubscribeEvent(key) 发布消息接口。 发布消息接口, type表示消息类型, data表示携带的数据。 void publishEvent(type, data)
- 我们采用的是是PA调FA机制, 所以需要新建一个JAVA远程服务Ability, 目前有Server和Internal两种类型的服务Ability, 此处不需要考虑多进程和 生命周期问题, 所以这里使用InternalAbility。 (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; }} (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) 处理取消订阅消息请求, 此逻辑比较简单, 将标识对应的订阅对象移除即可。 observers.remove(key) (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); } }); }} (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(); }}
- 新建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侧使用。 想了解更多关于开源的内容,请访问: 51CTO 开源基础软件社区 https://ost.51cto.com。

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

一个消息事件包含事件类型, 携带数据, 我们先定义一个JavaBean对象表示消息数据。
class Event {
private String type;
private String data;
}
消息数据模型有了, 可以开始定义接口了。
消息订阅接口。
key用于表示订阅者对象的标识. callback是消息的回调接口, 我们希望订阅者只接收到自己关心的事件, 所以还需要增加一个参数subscribeEventTypes表示关心的事件类型。
void subscribeEvent(key, subscribeEventTypes, callback)
取消订阅接口。
有订阅就会有取消, key用于表示订阅者对象的唯一标识。
void unSubscribeEvent(key)
发布消息接口。
发布消息接口, type表示消息类型, data表示携带的数据。
void publishEvent(type, data)
我们采用的是是PA调FA机制, 所以需要新建一个JAVA远程服务Ability, 目前有Server和Internal两种类型的服务Ability, 此处不需要考虑多进程和 生命周期问题, 所以这里使用InternalAbility。
(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;
}
}
(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) 处理取消订阅消息请求, 此逻辑比较简单, 将标识对应的订阅对象移除即可。
observers.remove(key)
(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);
}
});
}
}
(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();
}
}
新建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侧使用。