今天给你们讲一下在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框架环境下实现相似效果的思路。