WebViewClient shouldInterceptRequest冻结WebView

时间:2015-05-12 02:04:20

标签: android multithreading webview block freeze

我希望将WebView中显示的图像缓存特定时间,例如7天,所以我需要将图像缓存保存到磁盘并从磁盘加载它们并将它们提供给WebView。

另外,我需要调整图像大小以避免WebView;高内存使用率崩溃,因此我在名为" fetchBitmap "的阻止函数中实现了缓存调整大小逻辑。

正如Android文档所述," shouldInterceptRequest "在UI线程以外的线程上运行,所以我可以在这个函数中进行网络连接,但正如我所看到的,阻塞调用会导致WebView冻结。

该函数的行为方式迫使我使用阻止调用,而我无法通过Runnable for例如为了将来完成。

有任何解决方法吗?

webView.setWebViewClient(new WebViewClient() {

    private boolean isImage(String url) {
        if (url.contains(".jpg") || url.contains(".jpeg")
                    || url.contains(".png")) {
            return true;
        }
        return false;
    }

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        if (isImage(url)) {
            Bitmap bitmap = ImageUtil.fetchBitmap(url);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bitmap.compress(CompressFormat.JPEG, 100, bos);
            byte[] bitmapdata = bos.toByteArray();
            ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata);
            return new WebResourceResponse("image/*", "base64", bs);
        }
        return null;
    }
});

- UPDATE -

好的,我更改了逻辑,现在我只是从磁盘中阻止读取,并在runnable中单独处理网络负载(缓存); "的 fetchBitmapForWebView &#34 ;;当缓存不可用时,它会使网络负载加倍, 但是UI现在响应更快。

public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    if (isImage(url)) {
        Bitmap bitmap = ImageUtil.fetchBitmapForWebView(url);
        if (bitmap == null) {
            return null;
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.JPEG, 100, bos);
        byte[] bitmapdata = bos.toByteArray();
        ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata);
        return new WebResourceResponse("image/*", "base64", bs);
    }
    return null;
}

1 个答案:

答案 0 :(得分:1)

一般原则是你不应该在shouldInterceptRequest内进行任何繁重的处理,因为它是同步调用(虽然在另一个线程上)。对所有网络请求的调用都在同一个线程上处理,因此对一个请求进行阻塞也会导致所有其他请求被阻止。

对于您的用例,我会考虑在您的应用程序中运行一个小型Web服务器,它将执行所有必需的缓存和处理。当然,您还需要重写显示网页内的所有链接,以便指回本地服务器而不是原始Web服务器,因此在某些情况下可能会很麻烦。但作为一种通用方法,这将有助于减轻繁重工作并维护本地缓存。

周围有许多简单的Java Web服务器,例如: