Android WebView shouldInterceptRequest 异步加载
WebView 的 shouldInterceptRequest 可以让我们监听 WebView 发出的请求并做相应的处理,但有个严重的问题:浏览器的渲染以及资源加载都是在一个线程中,如果在 shouldInterceptRequest 处理时间过长,WebView 界面就会阻塞,这是非常不好的。
近期遇到一个问题,用 WebView 做显示,里面有个别特定 url 的图片需要做特殊的加载处理。所以就在 shouldInterceptRequest 判断 url,然后用 java 加载,处理,最后返回给 WebView。
一开始用 shouldInterceptRequest 做了如下处理:
@Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
Log.i(TAG, "shouldInterceptRequest url=" + url + ";threadInfo" + Thread.currentThread());
WebResourceResponse response = null;
if (url.contains("avatar.php?")) {
Bitmap bitmap = ImageLoader.getInstance().loadImageSync(url);
if (bitmap != null) {
InputStream in = IOUtils.bitmap2InputStream(bitmap, 100);
response = new WebResourceResponse("image/png", "UTF-8", in);
}
}
return response;
}
开始感觉没有什么大问题,一段时间后发现在网络环境差的情况下非常慢,要好半天加载动画才会消失(WebView 加载完成时取消加载动画的)。经调试发现所有 shouldInterceptRequest 的执行都在同一个线程内,如果此方法内处理时间长,不能及时返回结果,就会造成界面长时间无响应的情况。
改成异步加载即可:
@Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
Log.i(TAG, "shouldInterceptRequest url=" + url + ";threadInfo" + Thread.currentThread());
;
(url.contains()) {
{
();
(out);
ImageLoader.getInstance().loadImage(url, () {
{}
{}
{}
{
(bitmap != ) {
{
out.write(IOUtils.Bitmap2Bytes(bitmap));
out.close();
} (Exception e) {
e.printStackTrace();
}
}
}
});
response = (, , in);
} (Exception e) {
e.printStackTrace();
}
}
response;
}

