引言
我们知道,当我们需要重绘一个 View 的时候(onDraw ),通常我们有两个方法可供选择,invalidate 和 postInvalidate。
那么它们之间的关系与区别是什么呢?
本篇从源码角度分析 invalidate 与 postInvalidate 之间的关系区别。
分析
invalidate的代码调用路径:
1 | public void invalidate() { |
可以看到 invalidate 最后调用 invalidateInternal 去刷新,这里暂时不关心它们的具体实现。
然后再看看postInvalidate的代码调用路径:
1 | public void postInvalidate(int left, int top, int right, int bottom) { |
postInvalidate 其实是把 invalidate 这个操作封装成了一个 Message,post 到了 ViewRootImpl$ViewRootHandler 中去,最终在UI线程中调用了 View 的 invalidate。
我们知道,异步更新一个 View 会报"Only the original thread that created a view hierarchy can touch its views."(来自 ViewRootImplement$checkThread)的错误,
而 postInvalidate 可以在任意线程去调用,而不需要担心线程问题。
PS:很多人说『一定要在主线程更新 UI』,其实不然,仔细看这报错信息指得是 original thread,而这个线程是创建 ViewRootImpl 的线程,而不是特指主线程,只不过是绝大部分情况下是主线程,仅此而已。
小结
关系:
- postInvalidate 其实最终调用的就是 invalidate
差别:
- invalidate只能在 original thread 调用(一般就是主线程),而 postInvalidate 可以在任意线程调用。
这结论其实早就知道了,但是光知道这结论是远远不够的,要深入源码去理解,找出结论的由来;
慢慢地,会发现,其实那些知识点以及结论其实就是从源码里得来的;
自己看源码,会收获更多意想不到的知识。