今天给大家讲一下在 CC 框架下如何让我们的 jsBridge 更加优雅。
jsBridge 是作为 js 和 java 之间通信的桥梁,本身它的职责只是完成通信。
本文不是介绍 js 与 java 通信过程的实现,你可以使用第三方库( 如:JsBridge ),也可以自己来实现,或者用 addJavascriptInterface,都可以。本文的侧重点是如何让我们的 jsBridge 不那么臃肿,实现得更优雅,更利于维护。
但在实际封装过程中,会发现需要我们需要解决很多耦合的问题:
将具体的业务逻辑写在 jsBridge 模块中,本身就是一个灾难,而且随着业务类型的增加,最后这个 Activity/Fragment 会变得非常臃肿,而且难以复用
CC: Component Caller( github 地址 ),是一个 android 组件化开发框架,可支持包括 Activity 跳转、数据获取、网络请求等等几乎所有指令的跨组件调用。
组件实现方可自行决定是同步实现还是异步实现。
调用方可自行决定是同步调用还是异步调用 (注意: 不要在主线程同步调用耗时操作)。
并且组件调用可关联 Activity 和 Fragment 的生命周期(在 onDestroy 被调用时自动取消调用,避免出现内存泄露)
CC 框架的使用方式,可查看 github 中的 README 文档
CC 框架的实现原理 详细介绍
CC 框架为所有组件提供了统一的调用入口和回调结果格式。
所以,在 CC 框架下,js 调用 native 变得很简单:
流程图:
jsBridge 调用组件的核心代码如下:
- final String jsCallbackId = jsBridgeCallbackId; //本次js调用的回调id,用于回调
- String componentName = name;//调用的组件名称
- String actionName = action; //调用组件的actionName
- Map<String, Object> params = JsonUtil.toMap(json); //参数列表
- //统一使用这种方式进行CC调用,不用关心具体组件是如何实现的
- CC cc = CC.obtainBuilder(componentName)
- .setContext(activity) //可用于startActivity等需要Context的功能
- .steActionName(actionName)
- .setParams(params)
- .addParam("jsBridge", true) //标记一下是从jsBridge过来的调用
- .build();
- if (TextUtils.isEmpty(jsCallbackId)) {
- cc.callAsync(); //无需回调结果给js
- } else {
- cc.callAsyncCallbackOnMainThread(new IComponentCallback() {
- @Override
- public
- void
- onResult
- (CC cc, CCResult result)
- {
- String jsonResult = result.toString();
- sendResultToJs(jsCallId, jsonResult); //将结果回调给js
- }
- });
- }
是不是超级简单?
这样做的好处有:
确实有些功能必须要在 onActivityResult 中接收结果,例如:调用系统的选择联系人、从系统相册选择图片等。
其实,不止是 onActivityResult,还有获取权限的回调 onRequestPermissionsResult
这些功能在组件内部实现时,可以在组件中通过创建一个透明的 Activity 或 Fragment 来实现结果的接收,然后将结果发送给调用方:
- CC.sendCCResult(callId, result);
推荐使用 Fragment 方式实现
具体实现方式可参考如下开源库:
按照组件化开发的思想,是否需要登录才能用应由各组件自行判断。
需要在组件内部完成登录状态校验、打开登录界面、登录完成后再执行组件实际功能。
具体实现可参考另一篇文章: 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 框架环境下实现类似效果的思路。
来源: https://juejin.im/post/5a3fa7fe6fb9a045204c702f