基于腾讯 X5 内核的WebView开发:
1.onPageFinished
2.onProgressChanged()
3.合适的时机获取页面元素
业务需求是在 html 中注入 js脚本实现阅读模式切换功能。但是基于开源项目 mozilla/readability 开发,项目脚本过长,如果不能选定合适的时机注入,那么势必会影响用户交互。
在实现需求阶段,实现方式是在 onPageFinished() 注入 js。注入代码完成之后,在页面 ready() 状态中主动去通知客户端当前页面内容加载完成,并且是否可以切换阅读模式。根据前端的状态返回来确定客户端的表现。当然,这个过程是缓慢的,所以不建议直接加载阅读模式的html 。
注入代码留存:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private void (X5WebView webView, String scriptFile){
InputStream input;
try {
input = getActivity().getAssets().open(scriptFile);
byte[] buffer = new byte[input.available()];
input.read(buffer);
input.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
webView.loadUrl("javascript:(function() {" +
"var scriptElement = document.getElementById('readability-script');" +
//"alert(scriptElement);" +
"if(!scriptElement) {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var script = document.createElement('script');" +
"script.type = 'text/javascript';" +
// "script.async = 'true';" +
"script.id = 'readability-script';" +
// Tell the browser to BASE64-decode the string into your script !!!
"script.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(script);}" +
"})()");
} catch (IOException e) {
e.printStackTrace();
}
}
在功能完成之后,我们发现,有的网页出现解析代码运行之后通知客户端是可读的,但是我们并不能获取到展示的文本信息。导致切换阅读模式出现空白页面的情况。
这个 Bug 目前还没有解决,规避方案是当前页面的检测结果为可切换阅读模式页面并且可阅读文本不为空时,我们才会通知客户端该页面支持阅读模式的状态。我们目前选择了规避。
在页面调试时发现,上述的script标签内容导入了两次,虽然能够正常运行,但是无疑是增加了WebView消耗。
经过排查发现,在新网页开启时,会立即调用onPageStarted()和onPageFinished()方法,这个时候会第一次注入js,当页面完全加载完,WebView还是会回调一次onPageFinished()方法。那么这就是第二次的注入时机。
上面的分析合情合理,但是真实原因并不是这个,因为我们发现在第一次onPageFinished()调用的时候,我们在注入js之后会去主动调用注入的一个方法,通过 chrome://inspect 调试发现,这个时候调用的方法是Undefined状态,所以说我们的注入是失败的。那么也就说明一个猜测,第一次回调onPageFinished()时,网页并没有完成html基本的格式加载。为什么在没有完成加载最基础的标签时,我们会收到onPageFinished()回调呢,这简直就是一个大坑,这个问题还没有深入研究,待后续再说吧。
排除了上述这个原因,那么为什么会出现js导入多次的情况呢?
由于本人并不了解前端开发,所以出现这个问题才知晓了单页面应用的概念,具体的可以自行了解单页应用程序。
在单页面应用中,页面跳转中 标签内容是一直存在的。在主页注入标签之后,在后续的onPageFinished()方法中重复导入。就会造成注入冗余的情况。
终于找到原因所在,那么上述的注入代码中,修改了js部分的代码,先去确定标签不存在再去注入。
总结:
单页面应用在跳转时只会刷新