本篇文章介绍的搭建Android与Rn之间的简易通信架构,需要了解通信的基本使用的同学可以参考下面的链接

开篇先上图 - “简易版的通信架构图”

73d97d93d40d

RN与Android之间通信的架构图

本架构实现的功能有:

自定义通信规则,并以Json作为数据传输格式进行传输

实现通信场景分两种: 1) RN主动向Android获取数据 2)Android主动向RN传输数据

先着重介绍场景1(RN主动向Android获取数据),进行数据传输的格式

协议:rn://xxxmodule?funTarget=main_cache

协议的Schema:‘rn://’标识为此通信的标识,可验证通信正确性

协议的Host:‘xxxmodule’此标识为传递给对应的业务模块执行。包括:网络加载模块,本地数据缓存模块等等。

协议的queryParams: ‘funTarget’ 这个key用于标识模块需要执行的动作。比如网络模块需要拉取个人信息,需要拉取首页信息,此标识用于执行动作的区分

如下例子:

rn://networkmodule?funTarget=person_info, 到网络模块中拉取个人信息

rn://networkmodule?funTarget=main_page, 到网络模块中拉取首页信息

以上协议贯穿了整个架构的设计,下面介绍代码实现部分

协议规则实现类BridgeUrlConfig, BridgeUrlConst

public interface BridgeUrlConst {

String RN_SCHEMA = "rn";

String RN_NETWORK_MODULE = "network";

String COMPLETE_RN_SCHEMA = RN_SCHEMA + "://";

}

public enum BridgeUrlConfig {

//target: 网络模块

NETWORK_MODULE(BridgeUrlConst.COMPLETE_RN_SCHEMA + BridgeUrlConst.RN_NETWORK_MODULE),

//action: 网络模块下执行main_cache动作

NETWORK_SYNC_MAIN_CACHE(NETWORK_MODULE, "main_cache"),

//action: 网络模块下执行second_cache动作

NETWORK_SYNC_SECOND_CACHE(NETWORK_MODULE, "second_cache"),

//action: 网络模块下执行request动作

NETWORK_ASYNC_REQUEST(NETWORK_MODULE, "request");

private String target;

private BridgeUrlConfig parentConfig;

BridgeUrlConfig(String target) {

this.target = target;

this.parentConfig = null;

}

BridgeUrlConfig(BridgeUrlConfig parentConfig, String target) {

this.target = target;

this.parentConfig = parentConfig;

}

public String getTarget() {

return target;

}

public BridgeUrlConfig getParentConfig() {

return parentConfig;

}

}

以上使用接口常量与枚举实现规则定义, 更直观的方便我们后面的解析解析和判断的使用

如何使用协议?RN与原生通信入口 BridgeUrlAnalysis

//用来声明模块

public interface IModuleExecuteEntry {

/*

* funTarget: 需要执行的action

* argJson: 执行此action需要的参数

* promise: 用于执行结果的回调,可查看官网文档,上方链接有说

* 明。注意异步或同步兼用回调返回。

*/

void execute(String funTarget, String argJson, Promise promise);

}

//通信协议执行入口类

public class BridgeUrlAnalysis {

private static BridgeUrlAnalysis bridgeUrlAnalysis = new BridgeUrlAnalysis();

private BridgeUrlAnalysis() {

}

public static BridgeUrlAnalysis getInstance() {

return bridgeUrlAnalysis;

}

final Map modules = new HashMap<>();

//1.注册可执行模块

{

modules.put(URI.create(BridgeUrlConfig.NETWORK_MODULE.getTarget()).getHost(), new NetworkModule());

}

/**

* //2.通信入口方法

* 正确的url格式:‘ react_native://xxxmodule?funTarget='main_cache' "

*

* @param url

* @param argsJson

*/

public void analysis(String url, String argsJson, Promise promise) {

if (TextUtils.isEmpty(url)) {

throw new RuntimeException("please url not empty");

}

URI uri = URI.create(url);

if (!uri.getScheme().equals(BridgeUrlConst.RN_SCHEMA)) {

throw new RuntimeException("please url not correct");

}

//根据url中的host获取对应注册的module

String host = uri.getHost();

IModuleExecuteEntry entry = modules.get(host);

if (entry == null) {

throw new RuntimeException("this target module not init");

}

//解析url中的query,获取name为“funTarget”的值

String paramString = uri.getQuery().split("#")[0];

Matcher matcher = Pattern.compile("(^|&)" + "funTarget=" + "([^&]*)").matcher(paramString);

matcher.lookingAt();

entry.execute(matcher.group(2), argsJson, promise);

}

}

以上类需要注意两点:

1.注册可执行协议的模块

2.通信协议的入口执行逻辑

然后介绍场景2,Android主动发送数据给RN

此处使用了事件发送技术,类似EventBus的用法。

因为比较简单就直接上Android代码

/**

* 1.原生模块可以在没有被调用的情况下往 JavaScript 发送事件通知

*/

public interface INativeSendToRnBridge {

/**

* 发送事件到RN上

* @param eventName 设置发送事件的名称,RN可对此名称的事件进行监听

* @param jsonObj

*/

void sendEvent(String eventName, String jsonObj);

}

/**

*具体实现类

*/

public class AndroidSendToRNBridge implements INativeSendToRnBridge {

private ReactContext mReactContext;

public AndroidSendToRNBridge(ReactContext context) {

this.mReactContext = context;

}

/**

* 发送数据的入口,规定了发送事件的格式

* eventName: 用于区分事件,相当于key

* jsonObj: 事件所包含的数据,相当于value。建议以Json格式数

* 据发送

*/

@Override

public void sendEvent(String eventName, String jsonObj) {

mReactContext

.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)

.emit(eventName, jsonObj);

}

public ReactContext getReactContext() {

return mReactContext;

}

public void setReactContext(ReactContext mReactContext) {

this.mReactContext = mReactContext;

}

}

本篇文章介绍完毕啦,需要源码的小伙伴可私信我。

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐