android JSBridge的加载时机问题

https://github.com/lzyzsd/JsBridge 也算是比较悠久和使用了。
可供参考的android和IOS,以及前端的使用 https://segmentfault.com/a/1190000018208609

遇到的问题:
比如:

  1. 从前端在加载WebView的时候,执行了某些动作,一直得不到回应,过一会儿会瞬间刷刷刷执行多次;
  2. 某个初始化指令,前端是调用了,但是android端需要等很久才能生效,或者不生效。

上述类似的问题,可以研究下我这段分析。

WebView和Html加载时机的关系

这里我不做更深入的讨论。简要地解释下:
android的WebView,其实就是Chrome的内核,与我使用过CEF框架,javafx等Webkit内核其实类似。

标准浏览器,做到客户端上,WebView(不是android也会类似有)2个函数:
public void onPageStarted(xxx)
public void onPageFinished(xxx)
onLoadResource(xxx, url)

  • onLoadResource,指代的是,跳转新url,或者内部中转的url,又或者加载某图片资源,视频资源之前的回调,因此我们这里在这里进行一些url跳转或者做无图浏览,或者做爬虫的时候,加速加载,那么我们可以进行一些拦截;

  • onPageStarted, 指代的是,开始加载url,每一次有一个新的url需要打开都会执行,那么,它可能会有多次执行;

  • onPageFinished,指代的是,其实对应的是,网页所有的资源,DOM全部准备好了才回调。而这个回调,可能是很难完成的,比如JS有些无法加载,某些资源需要下载很久很慢;

JSBridge代码分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从上述,可以看出,jsbridge的框架中,需要等待onPageFinished以后,才会干2个事情:

第一,加载js代码,初始化jsbridge,通知ready:
执行WebViewJavascriptBridge.js的代码,主要是通知’WebViewJavascriptBridgeReady"。
而前端JS代码中:
document.addEventListener(
‘WebViewJavascriptBridgeReady’,
function () {
registerAppEvent()
isInitBridgeEvent = true
},
false
)
进行了注册,监听,等待着native的通知ready。

第二,执行JS的排队中的指令队列:
我们可以看到android jsbridge库代码中,做了一个startupMessage的队列,用来存储前端发下来的执行,等待onFinish才将它统一执行和干活。

解决方案

看到这里,那么,针对前面的2个问题就迎刃而解了。
在BridgeWebViewClient里面:

   private var isLoadedBridgeJs = false

mBinding.webView.webViewClient = object : BridgeWebViewClient(mBinding.webView) {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
                lifecycleScope.launch {
                    delay(500)
                    if (!isLoadedBridgeJs) { //父类执行了js的逻辑,则这里不再需要处理
                        isLoadedBridgeJs = true
                        //**warn** jsbridge的代码逻辑: onPageFinished才进行初始化逻辑;
                        // 而Finished的时机可能非常晚(网页的dom资源需要加载完成才算数)!
                        // 而started则很快。
                        //常规不能这样调用,这里因为父类BridgeWebViewClient 的finish只做了JS和处理排队事务,才能这样调用。不理清楚逻辑,不得任意修改。
                        super.onPageFinished(view, url)
                    }
                }
                ///xxxx
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                isLoadedBridgeJs = true //父类执行了js的逻辑,则这里不再需要处理
                //xxxx
            }
        }
    }

这里是通过delay一段时间,来裸调用父类的onPageFinished。因为父类的onPageFinished函数里面的干的活,很纯粹,才这样写。
否则还是尽量去继承或者下载库代码来改造。

并且从JS代码可以看出,多次执行并不影响。 if (window.WebViewJavascriptBridge) { return; }有做拦截。

同时,delay(500)的时间,最好是大一点没有关系,建议300-800ms。
因为默认情况,onPageFinished会比较快回调(没有大资源和错误JS,资源的情况下)。
那么,我们的代码通过isLoadedBridgeJs来控制,就不会执行。而是库自行执行了。

如果,500ms,还没有finished来,我们先执行一次,初始化好JSBridge,同时执行一下js端的初始化任务。
等到真正的finished来了以后,再次执行默认的,并没什么影响。

具体的版本具体分析参考。
目前的代码参考的是jsbridge1.0.4。
据我来看1.0.5也照样会有这样的问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值