Webview的shouldInterceptRequest可以让我们拦截Webview发出的请求并作出相应处理,例如监听到请求某个JS后直接回调本地对应文件可以减少连接远程服务器及请求资源的时间,但由于浏览器渲染及资源的加载都在一个线程中,如果在shouldInterceptRequest 频繁做磁盘I/O操作(读取本地js、css、图片等等),会影响weview加载速度。
WebView请求拦截代码:
@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;
}
优化思路:在应用启动时将预置资源加载到内存中使用ByteArrayOutputStream缓存起来,使用时再转换成InputStream,减少磁盘I/O耗时。
public class InputStreamCacher {
private static final String TAG = "InputStreamCacher";
/**
* 将InputStream中的字节保存到ByteArrayOutputStream中。
*/
private static Map<String, ByteArrayOutputStream> outputStreamMap = new HashMap<String, ByteArrayOutputStream>();
private InputStreamCacher(){}
//采用内部类实现线程安全的单例模式
public static InputStreamCacher getInstance(){
return InputStreamCacherHolder.inputStreamCacher;
}
private static class InputStreamCacherHolder{
private static final InputStreamCacher inputStreamCacher = new InputStreamCacher();
}
/**
* 返回缓存资源名称集合
* @return
*/
public Set<String> getKeySet(){
return outputStreamMap.keySet();
}
/**
* 把输入流保存到ByteArrayOutputStream中
* @param resName
* @param inputStream
*/
public void putInputStream(String resName, InputStream inputStream) {
if (CMUTools.isTextEmpty(resName) || null == inputStream)
return;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) > -1 ) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
outputStreamMap.put(resName, byteArrayOutputStream);
inputStream.close();
} catch (IOException e) {
CMULog.e(TAG, e.toString());
}
}
/**
* 根据资源名称获取输入流
* @param resName
* @return
*/
public InputStream getInputStream(String resName) {
ByteArrayOutputStream byteArrayOutputStream = outputStreamMap.get(resName);
if(CMUTools.isTextEmpty(resName) || null == byteArrayOutputStream){
return null;
}
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
}
缺点:内置资源较大时会比较消耗手机内存空间,一般只需缓存js、css、html等体积较小的文件。
网友评论