WebView中用shouldInterceptRequest+Picasso加载图片,多图时UI短暂无响应求助
解决WebView中用Picasso加载大量图片导致UI卡顿的问题
这个问题我之前也碰到过!核心原因就是shouldInterceptRequest方法是运行在UI线程的,如果你在这里直接做同步的图片加载操作(比如调用Picasso的get()方法),当HTML里包含大量图片时,UI线程会被频繁阻塞,自然就出现短暂无响应的情况了。
解决方案思路
我们要彻底避免在UI线程做任何耗时操作,转而利用Picasso的缓存机制来优化:
- 优先从Picasso的内存/磁盘缓存中读取图片,这是本地IO操作,速度极快,不会阻塞UI。
- 如果缓存中没有目标图片,就让WebView默认处理图片加载(WebView本身自带异步加载逻辑),同时在后台用Picasso预加载该图片到缓存,后续再加载同一张图时就能直接复用缓存了。
具体代码实现
webView.setWebViewClient(new WebViewClient() { // 适配Android 5.0及以上版本 @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); handleImageRequest(url); return super.shouldInterceptRequest(view, request); } // 兼容低版本Android系统 @SuppressWarnings("deprecation") @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { handleImageRequest(url); return super.shouldInterceptRequest(view, url); } // 抽离图片请求处理逻辑,让代码更清晰 private void handleImageRequest(String url) { String mime = URLConnection.guessContentTypeFromName(url); if (mime != null && mime.startsWith("image")) { Picasso picasso = Picasso.get(); try { // 尝试从Picasso缓存中获取图片文件 File cacheFile = new File(picasso.getCache().getKey(url)); if (cacheFile.exists()) { // 如果缓存存在,你可以选择直接返回WebResourceResponse(按需使用) // 这里不强制拦截,让WebView自己读取缓存也完全没问题 } else { // 缓存不存在,后台异步预加载到缓存 picasso.load(url).fetch(); } } catch (Exception e) { e.printStackTrace(); } } } });
要是你确实需要拦截图片请求并自己返回流,一定要确保读取缓存的操作不会阻塞UI——上面的代码里读取缓存文件是本地操作,速度很快,不会有问题,但绝对不能在这里做网络请求!
额外优化建议
- 配置Picasso的缓存大小,减少重复网络请求:
Picasso picasso = new Picasso.Builder(context) .memoryCache(new LruCache(1024 * 1024 * 50)) // 50MB内存缓存 .diskCache(new DiskCache(context, "picasso-cache", 1024 * 1024 * 200)) // 200MB磁盘缓存 .build(); Picasso.setSingletonInstance(picasso); - 对图片URL做去重处理,比如用一个
Set记录已经发起预加载的URL,避免重复调用fetch()。
内容的提问来源于stack exchange,提问作者KpSt
相关产品推荐
相关产品推荐

