大家好,我系苍王。
以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。
大家应该都有或多或少都会接触到Webview的封装和开发,一般都是在默认进程中开启一个Web的Activity来做操作。但是近来越来越多人会偏向于将Webview单独一个进程来做处理。
WebView进程的好处:
1.不占用主进程内存,减少主进程内存压力,减少系统强制回收的可能性。
2.Webview如果存在内存泄露,内存会更加宽裕,只要关闭就了事了,不会对主进程有过多影响。
3.进程隔离,如果出现崩溃不会相互影响,并且可以做一些拉活操作。
Android开启单独进程的方式,在以前的进程化已经介绍过了,WebView通过依赖于Activity来做单独进程,开启Activity单独进程,只要在AndroidMainfest中声明Activity的时候添加android:process=":xxx"属性
哈哈,这些简单的介绍,估计大家都懂,接下来就是展示真正技术的时候了。
JSBridge原理
JsBridge,如果大家有做过Webview和客户端的js调用,相信大家都会接触这个框架,这个框架兼容android和ios端,提供了js对android和ios端的互相调用方案。
因为WebView是单独进程的,其实大家都不喜欢WebView和其他业务过分耦合,那么就需要让WebView和jsbridge做一些封装。
下面是jsbridge原理,jsbridge通过注入js调用代码到html里面,html中通过调用相应函数,然后jsbridge通过shouldOverrideUrlloading来拦截对应拼接的字符串,然后回调到注册触发的webview注册的registerHandler函数完成方法实现。
jsbridge调用原理.png
说一下两点jsbridge使用需要注意的地方。
1.Webview必须注册BridgeWebViewClient。
2.onPageFinished和shouldOverrideUrlLoading覆写时,一定要调用supper的方法,不然注入和回调将无法触发。
JsBridge基本回调框架建立
我们现在要做的controller到webview的封装,这里只是共同进程里面的封装。
先建立一个业务类注册的jsbridge管理类
data class JsBean(val functionName: String, val url: String?, val result: (context: Context?, data: String, data2: String, callBack: IJavaScriptCallBack?) -> String?)
object JavaScriptInterface {
val set: MutableSet = HashSet()
//jsbridge接收的scheme名
val SCHEME_NAME = "eating"
var context: Context? = null
fun register(bean: JsBean) {
set.add(bean)
}
fun unregister(bean: JsBean) {
set.remove(bean)
}
}
2.业务初始化时调用JsBridge的注册
JavaScriptInterface.register(JavaScriptInterface.JsBean(
"groupgame",
""
) { context, data, data2, callback ->
……自身逻辑……
data //返回值
})
3.编写jsbridge注册回调
//非跨进程使用,fragment或webview使用
fun inject(context: Context, url: String, webView: NestedScrollWebView) {
//html调用得方法名为sendAction
webView.registerHandler("sendAction") { data, function ->
//解析为uri
val uri = Uri.parse(data)
//比对scheme名
if (uri.scheme == SCHEME_NAME) {
//比对想要触发的方法名
set.filter { uri.authority == it.functionName }
//调用jsbean触发的方法
.mapNotNull { it.result(context, uri.pathSegments[0], "", null) }
//回调给html
.forEach { function.onCallBack(it) }
}
}
}
4.在webViewActivity初始化的时候注册
JavaScriptInterface.inject(context, url, web)
Jsbridge独立进程封装
这里当然是要调用aidl的,之后优化的话封装Binder。
跨进程jsbridge.png
jsbridge到web的部分是共通的,流程图中就不展示了。
1.编写aidl接口
```
//关闭web页的接口,回调给webActivity的实现
interface IJavaScriptCallBack {
void callbackFinish();
}