blink渲染知识7-webview和android的交互

http://blog.csdn.net/hongbomin/article/details/18499295
WebView本身是一个layout, 他和android的view系统交互的方法是:
当webview本身内容有变化时,需要更新到android系统时,WebView的invalidate函数被调用,实际的调用栈:
BrowserViewRenderer.cc中
->client_->PostInvalidate();
->AwContents::PostInvalidate
->Java_AwContents_postInvalidateOnAnimation
->AwContents.java, postInvalidateOnAnimation
->containerView, 也就是WebView.postInvalidate等操作。
这样就会告知android我们自己的内容变化了,需要重新绘制。
之后,android绘制框见就会调用webview.onDraw函数,从我们webview里面取出我们的绘制结果到canvas里,然后拿走和其他view的onDraw的结果拼凑起来显示给用户。

Webview.onDraw被调用,应该并不是每次调用都会完成一次本地的绘制,但是至少能够同步拿走一些数据。此外会异步触发一些绘制,比如告知内核要beginframe, 等等。

摘要
从应用程序层次来看,WebView只是一个视图(View)部件而已,与普通的TextView一样,它可以被嵌入在应用程序的任何一个位置,所以,尽管WebView是一个较为复杂的视图部件,但仍然工作在Android视图系统的绘制模型下。
绘制模型 vs. 渲染模型
事实上,绘制模型和渲染模型两个术语可以混用。但本文还是对两者做了细微的区分。当谈及与Android视图系统整合,使用“绘制模型”术语说明 Android View系统的绘制模型是如何作用到WebView部件上,而谈及WebView内页面内容的合成方式时,使用“渲染模型”术语描述以何种方式将页面内容 渲染到由绘制模型中给定的Canvas对象上。两者的联系是,渲染模型会根据绘制模型中的Canvas对象决定采取何种渲染方式。
WebView的绘制模型
Android SDK中,android.webkit.WebView实际上是一个ViewGroup,并将后端的具体实现抽象为WebViewProvider,而 WebViewChromium正是一个提供基于Chromium的具体实现类,对核心类AwContents做了一层简单的封装,加强了对线程安全方面 的考量。大致结构如下图所示:

简单的来说,当一个视图(View)部件的内容发生更新时,会调用invalidate()方法通知Android视图系统表明这个View的内容 已经失效,视图系统会根据view层次结构计算有哪些View需要重绘,并调用View.draw方法将更新的内容绘制到传入Canvas上,对于用户自 定义的View,绘制的逻辑代码实现在重载地View.onDraw方法中,决定在在Canvas上绘制什么内容。关于Android视图系统的绘制模 型,详细信息可参考这里。
再回到WebView的情况。当WebView部件发生内容更新时,例如页面加载完毕,CSS动画,或者是滚动、缩放操作导致页面内容更新,同样会 在WebView触发invalidate方法,随后在视图系统的统筹安排下,WebView.onDraw方法会被调用,最后实际上调用了 AwContents.onDraw方法,它会请求对应的native端对象执行OnDraw方法,将页面的内容更新绘制到WebView对应的 Canvas上去,至此,就像按下了WebView渲染器的启动开关,一个完整的渲染流水线开始工作了。
1. WebViewChromium::onDraw(Canvas canvas) (WebViewChromium.java in AOSP) 
2. --> AwContents::onDraw(Canvas canvas) (AwContents.java in chromium) 
3.     --> android_webview::AwContents::OnDraw(...) (aw_contents.cc) 
4.         -->  android_webview::InProcessViewRenderer::OnDraw(...) (in_process_view_renderer.cc) 

绘制方法OnDraw
Native端InProcessViewRenderer对象负责响应从Java层发出的OnDraw调用请求,首先会根据判断硬件加速是否开启,决定渲染的执行路径。
1. bool InProcessViewRenderer::OnDraw(jobject java_canvas, 
2.                                    bool is_hardware_canvas, 
3.                                    const gfx::Vector2d& scroll, 
4.                                    const gfx::Rect& clip) { 
5.   scroll_at_start_of_frame_  = scroll; 
6.   if (is_hardware_canvas && attached_to_window_ && HardwareEnabled()) { 
7.     // We should be performing a hardware draw here. If we don't have the 
8.     // comositor yet or if RequestDrawGL fails, it means we failed this draw and 
9.     // thus return false here to clear to background color for this draw. 
10.     return compositor_ && client_->RequestDrawGL(java_canvas); 
11.   } 
12.   // Perform a software draw 
13.   return DrawSWInternal(java_canvas, clip); 
14. } 
上面的代码片段中,OnDraw方法接受四个参数,
1. java_canvas:Java层Canvas对象在JNI层的native表示,对这个Canvas的绘制实际上是在更新WebView部件的内容;
2. is_hardware_canvas:布尔值,标识java_canvas对象是否启用了硬件加速的Canvas对象,在Java层通过调用Canvas.isHardwareAccelerated()来获取;
3. scroll:因屏幕滚动而发生的偏移;
4. clip:WebView部件内容发生更新的矩形区域;
显然,OnDraw有两条不同的执行路径:
硬件渲染路径:当同时满足 1)WebView的Canvas开启了硬件加速;2)当WebView与一个Window关联后;3)没有通过命令行选项--disable- webview-gl-mode禁用WebView的GL模式等这三者条件时,会请求Client对象调用RequestDrawGL以硬件方式绘制 Canvas。RequestDrawGL方法最终还是会调用InProcessViewRenderer::DrawGL,但其中涉及到Java层和 JNI的互操作性问题,调用过程看起来不是那么直接了当,后续文章将会详细介绍。
软件渲染路径:当上述三者条件不满足时,调用DrawSWInternal方法以软件方式绘制 Canvas。而DrawSWInternal还会考虑两种情况,1)从AOSP编译的WebView;2)从Chromium编译的WebView。两 者不同之处在于,是否提供了直接访问Java层Canvas对象中Pixels的函数表,对于从AOSP编译的WebView,可以直接将Java层 Canvas对象转换为SkCanvas,合成器(compositor)直接将合成的内容渲染到这个Canvas上。而从Chromium编译出来的 WebView,编译期是不能直接访问AOSP代码,也就是说不能直接将Canvas对象转换为SkCanvas,需要先调用NDK方法创建一个 Bitmap,合成器只能先将页面内容渲染到这个Bitmap上,然后再通过JNI调用Java层的drawBitmap将这个Bitmap绘制到 Canvas对象上。
小结:
WebView只是一个普通的View部件而已,当页面内容更新时,会触发invalidate,Android视图系统收到失效消息后会要求 WebView部件回调onDraw方法重绘自己。WebView重绘过程较为复杂,方法InProcessViewRenderer::OnDraw是 理解和分析WebView渲染模型的入口点,Canvas对象的硬件加速属性决定了渲染路径的不同。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值