通常开发hybrid应用时, 很多页面都可能使用相同的一些资源(例如一些常用的js框架, css库之类的), 那么将这些资源内置到app中, 使webview直接加载本地的资源, 带来的好处显而易见: 不仅节约流量而且还能加快页面的加载.

实现 (假设我们要缓存 zepto.min.js)

将要缓存的js文件放到 assets 目录下:

假设路径为: assets/offline_res/zepto.min.js

在WebView启动前(比如在Activity的onCreate中),先取出本地文件的路径

private final Set offlineResources = new HashSet<>();

private void fetchOfflineResources() {

AssetManager am = getAssets();

try {

String[] res = am.list("offline_res");

if(res != null) {

Collections.addAll(offlineResources, res);

}

} catch (IOException e) {

e.printStackTrace();

}

}

在WebView加载资源的时候进行拦截, 如果本地有, 直接使用本地文件

//重写 WebViewClient.shouldInterceptRequest() 方法

@Override

public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

Log.d("WebViewActivity", "shouldInterceptRequest thread id: " + Thread.currentThread().getId());

int lastSlash = url.lastIndexOf("/");

if(lastSlash != -1) {

String suffix = url.substring(lastSlash + 1);

if(offlineResources.contains(suffix)) {

String mimeType;

if(suffix.endsWith(".js")) {

mimeType = "application/x-javascript";

} else if(suffix.endsWith(".css")) {

mimeType = "text/css";

} else {

mimeType = "text/html";

}

try {

InputStream is = getAssets().open("offline_res/" + suffix);

Log.i("shouldInterceptRequest", "use offline resource for: " + url);

return new WebResourceResponse(mimeType, "UTF-8", is);

} catch (IOException e) {

e.printStackTrace();

}

}

}

Log.i("shouldInterceptRequest", "load resource from internet, url: " + url);

return super.shouldInterceptRequest(view, url);

}

注意: WebViewClient.shouldInterceptRequest() 方法是在WebView管理的子线程中执行的, 所以重写该方法时, 要保证线程安全.

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐