WebViewClient shouldInterceptRequest冻结WebView [英] WebViewClient shouldInterceptRequest Freezes the WebView

查看:650
本文介绍了WebViewClient shouldInterceptRequest冻结WebView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to cache images displayed in the WebView for a specific time, for e.g. 7 days, so I needed to both save image caches to disk and load them from disk and provide them to the WebView.

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

Also I needed to resize the images to avoid the WebView; Crash on High Memory Usage, so I implemented the caching and resizing logic in a Blocking Function named "fetchBitmap".

正如Android文档所述," shouldInterceptRequest "在UI线程之外的其他线程上运行,因此我可以在此函数中进行联网,但是正如我所看到的,阻塞调用导致WebView冻结.

As the Android documentation states, the "shouldInterceptRequest" runs on a Thread Other than the UI Thread, so I can do networking in this function, but as I can see, a blocking call causes the WebView to Freeze.

该函数的行为方式迫使我使用 blocking 调用,而我无法传递Runnable,例如以便将来完成.

The way the function behaves forces me to use a blocking call, and I can't pass a Runnable for e.g. for a future completion.

有什么解决方法吗?

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;
    }
});

-更新-

好的,我改变了逻辑,现在我只是阻止从磁盘读取,并在一个可运行的程序中分别处理网络负载(缓存); " fetchBitmapForWebView ";当缓存不可用时,它将使网络负载增加一倍, 但用户界面现在响应速度更快.

OK, I changed the logic, now I just Block Read from the disk, and handle the network load (caching) separately in a runnable; "fetchBitmapForWebView"; it doubles the network load when the cache is not available, but the UI is now more responsive.

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;
}

推荐答案

一般原则是,您不应在shouldInterceptRequest内部进行任何繁重的处理,因为它是一个同步调用(尽管在另一个线程上).所有网络请求的调用都在同一线程上处理,因此阻塞一个请求将导致所有其他请求也被阻塞.

The general principle is that you shouldn't do any heavy processing inside shouldInterceptRequest, as it is a synchronous call (albeit on another thread). Calls for all network requests are processed on the same thread so blocking for one request will cause all of the other requests to be blocked as well.

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

For your use case, I would consider running a small web server inside your app, which will do all the required caching and processing. Surely, you will also need to rewrite all the links inside displayed web pages in order to point back to the local server instead of the original web server, so it may be cumbersome in some situations. But as a general approach this will help greatly with off-loading heavy work and maintaining a local cache.

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

There are numerous simple Java web servers around, for example:

  • https://github.com/NanoHttpd/nanohttpd
  • https://github.com/nikkiii/embedhttp
  • https://github.com/google/webview-local-server

这篇关于WebViewClient shouldInterceptRequest冻结WebView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆