本篇文章介紹的搭建Android與Rn之間的簡易通信架構,需要了解通信的基本使用的同學可以參考下面的鏈接
開篇先上圖 - “簡易版的通信架構圖”
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;
}
}
本篇文章介紹完畢啦,需要源碼的小伙伴可私信我。