WebView加载HTML后绘制Bitmap首次正常后续为空问题咨询
问题原因
- 引用对象不匹配:你在
onPageFinished回调中调用createBitmapFromView时,方法内使用的是全局mView变量,而非当前回调返回的已加载完成的WebView实例。每次调用Print()方法都会新建一个WebView,但绘制时仍指向之前可能已经被回收/失效的旧View,导致后续生成Bitmap为空。 - 回调时机错误:
WebViewClient.onPageFinished仅代表WebView完成了资源加载流程,不代表页面内容已经完成渲染。后续调用时如果存在缓存,内核会快速回调onPageFinished,此时页面还没完成绘制,测量得到的宽高为0,生成的Bitmap自然为空。 - 离屏渲染未开启:未添加到视图树的WebView默认不会开启离屏绘制,首次加载可能因为时序问题刚好渲染完成,后续复用内核资源时就会出现无法绘制到Canvas的情况。
修复方案
1. 修正绘制对象引用
修改createBitmapFromView方法,把要绘制的View作为参数传入,避免引用全局的旧View,同时增加宽高合法性判断:
public Bitmap createBitmapFromView(View view) { view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); if (view.getMeasuredWidth() <= 0 || view.getMeasuredHeight() <= 0) { return null; } Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bitmap); view.draw(c); return bitmap; }
2. 修正WebView配置和回调逻辑
开启离屏渲染,禁用缓存避免历史内容干扰,同时调整等待时机确保渲染完成:
public void Print() { WebView mWebView = new WebView(activity); // 开启离屏渲染,允许未挂载到视图树的WebView绘制内容 mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); mWebView.setInitialScale(400); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setVerticalScrollBarEnabled(false); mWebView.getSettings().setDefaultTextEncodingName("utf-8"); mWebView.getSettings().setUseWideViewPort(true); // 禁用缓存避免历史内容干扰 mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); mWebView.addJavascriptInterface(new JavaScriptInterface(), "HTMLOUT"); mWebView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { // 等待渲染完成后再执行绘制 view.postDelayed(() -> { Bitmap myBitmap = createBitmapFromView(view); if (myBitmap != null) { print(myBitmap); } // 用完销毁WebView避免内存泄漏和缓存干扰 view.destroy(); }, 100); } }); mWebView.loadData(mHtmlString, "text/html; charset=UTF-8", null); }
3. 兜底处理
如果延迟后仍然偶现空Bitmap,可以在createBitmapFromView返回空时重试1-2次,最多重试3次避免死循环。
内容的提问来源于stack exchange,提问作者erkan demir
相关产品推荐
相关产品推荐

