今天給你們講一下在CC框架下如何讓咱們的jsBridge更加優雅。javascript
jsBridge是做爲js和java之間通訊的橋樑,自己它的職責只是完成通訊。java
本文不是介紹js與java通訊過程的實現,你可使用第三方庫(如:JsBridge),也能夠本身來實現,或者用addJavascriptInterface,均可以。本文的側重點是如何讓咱們的jsBridge不那麼臃腫,實現得更優雅,更利於維護。android
但在實際封裝過程當中,會發現須要咱們須要解決不少耦合的問題:git
將具體的業務邏輯寫在jsBridge模塊中,自己就是一個災難,並且隨着業務類型的增長,最後這個Activity/Fragment會變得很是臃腫,並且難以複用github
CC框架爲全部組件提供了統一的調用入口和回調結果格式。web
因此,在CC框架下,js調用native變得很簡單:json
流程圖:app
JsBridge的核心代碼以下:框架
public class JsBridge {
private WeakReference<WebView> webViewWeakReference;
public JsBridge(WebView webView) {
this.webViewWeakReference = new WeakReference<WebView>(webView);
}
@JavascriptInterface
public void callNativeCC(String componentName, String actionName, String dataJson, final String callbackId) {
final WebView webView = webViewWeakReference.get();
if (webView == null) {
return;
}
Map<String, Object> params = null;
if (!TextUtils.isEmpty(dataJson)) {
try {
JSONObject json = new JSONObject(dataJson);
params = JsonUtil.toMap(json); //參數列表
} catch (JSONException e) {
e.printStackTrace();
}
}
//統一使用這種方式進行CC調用,不用關心具體組件是如何實現的
CC cc = CC.obtainBuilder(componentName)
.steActionName(actionName)
.setContext(webView.getContext()) //可用於startActivity等須要Context的功能
.setParams(params)
.build();
if (TextUtils.isEmpty(jsCallbackId)) {
cc.callAsync(); //無需回調結果給js
} else {
cc.callAsyncCallbackOnMainThread(new IComponentCallback() {
@Override
public void onResult(CC cc, CCResult result) {
//將結果回調給js
webView.loadUrl("javascript: callback(" + callbackId + "," + result + ")");
}
});
}
}
}
複製代碼
是否是超級簡單?異步
這樣作的好處有:
確實有些功能必需要在onActivityResult中接收結果,例如:調用系統的選擇聯繫人、從系統相冊選擇圖片等。
其實,不止是onActivityResult,還有獲取權限的回調onRequestPermissionsResult
這些功能在組件內部實現時,能夠在組件中經過建立一個透明的Activity或Fragment來實現結果的接收,而後將結果發送給調用方: CC.sendCCResult(callId, result);
推薦使用Fragment方式實現
具體實現方式可參考以下開源庫:
透明Activity方式實現的權限申請庫:AndPermission, 參考類:PermissionActivity.java
Fragment方式實現的權限申請庫: RxPermissions,參考類:RxPermissions.java
按照組件化開發的思想,是否須要登陸才能用應由各組件自行判斷。
須要在組件內部完成登陸狀態校驗、打開登陸界面、登陸完成後再執行組件實際功能。
具體實現可參考另外一篇文章: CC框架實踐(1):實現登陸成功再進入目標界面功能
在沒有使用CC框架的狀況下,也能夠實現相似效果的。思路以下:
public interface IJsCall {
String name(); //功能的名稱,供js調用
void handleJsCall(JSONObject params, IJsCallback callback);
}
public interface IJsCallback {
void callback(String result);
}
複製代碼
public class JsCallManager {
private final Map<String, IJsCall> map = new HashMap<>();
public static final String DEFAULT_RESULT = "{\"success\":false}";
void init() {
//用於IJsCall自動註冊到list
//使用AutoRegister插件將生成以下代碼:
// registerJsCall(new JsCallA());
// registerJsCall(new JsCallB());
}
void registerJsCall(IJsCall call) {
if (call != null) {
map.put(call.name(), call);
}
}
public void onJsCall(String name, JSONObject json, IJsCallback callback) {
IJsCall jsCall = map.get(name);
if (jsCall != null) {
jsCall.handleJsCall(json, callback);
} else {
callback.callback(DEFAULT_RESULT);
}
}
}
複製代碼
本文介紹了在CC框架下用組件調用的方式讓jsBridge實現跟具體業務徹底解耦。並給出了非CC框架環境下實現相似效果的思路。