setContentView
只要你使用过Activity,那么你一定使用过setContentView这个方法。一般都是这样调用该方法:
然后,在手机或者模拟器上就可以看见自己的布局。
如果,你留意的话,setContentView还有很多过载方法:


那么,getWindow()方法是做什么的呢?一探究竟:
可以看出,该方法返回一个Window实例。但是Window是一个抽象类啊,怎么可以有实例对象???原来,Window类有一个子类PhoneWindow,那么如何得知getWindow返回的是PhoneWindow实例呢?来,看下面这张图:
至此,您应该明白setContentView()方法是调用PhoneWindow类的同名方法。源码如下:


每个Activity都会实例化一个Window并且只有一个,而View就像是贴在Window上的装饰品。窗户(Window)只有一个,但是窗花(View)可以有很多。
LayoutInflater
获得 LayoutInflater 实例


对于第一种,主要是调用 Activity 的 getLayoutInflater() 方法。
继续跟踪研究 android 源码,Activity 中的该方法是调用 PhoneWindow 的 getLayoutInflater()方法!
可以看出它其实是调用 LayoutInflater.from(context), 那么该方法其实是调用第二种方法,看看源码,如下:


inflate 方法
inflate 原意是充气之类的,在这里主要意思就是,扩张、使之膨胀。换句话说就是将当前视图view补充完整、扩展该视图。


示例代码:


对于上面代码,指定了第二个参数 ViewGroup root,当然你也可以设置为 null 值。
注意:该方法与 findViewById 方法不同。
inflater 是用来找 layout 下 xml 布局文件,并且实例化!而 findViewById() 是找具体 xml 下的具体 widget 控件(如: Button,TextView 等)。
postInvalidate() (参考)
在子线程中控制UI:


postInvalidate() 方法,源码:


其实,是调用了 Handler 的处理消息的机制!该方法可以在子线程中直接用来更新UI。但是在 Button 的事件中开启线程,更新 UI就会报错报异常。
Handler 和 invalidate 方法结合多线程更新 UI
方法 invalidate 主要用在主线程中(即UI 线程中),不可以用于子线程。如果在子线程中需要使用 postInvalidate 方法。


invalidate 方法如果你直接在主线程中调用,是看不到任何更新的。需要与Handler结合!
Android 在 onDraw 事件处理绘图,而 invalidate() 函数可以再一次触发 onDraw 事件,然后再一次进行绘图动作。


经过测试,发现 times 一直在++,说明 onDraw 被多次调用,并且一直在画图!
注释掉的话:
可以看出,图像只画了一条线,说明onDraw()方法被调用一次。从log上也可以看出来:
那么,是什么力量促使onDraw()方法被调用呢?
setContentView()View view方法,其实是调用PhoneWindow的setContentView(View view)方法,调用关系如下:
从而可以看出,invalidate()方法是促使onDraw()方法被调用的力量。
那么,修改代码,将内部类MyView的onDraw()方法中的invalidate()注释取消,再看看运行效果:
控制台:


可以看出,invalidate()方法使onDraw()一直被调用,实现重绘的效果。
在invalidate()方法源码中,有这么一段注释:
这段话,说明了上面的实现(调用onDraw()方法)。但是在子线程中必须使用postInvalidate()方法。
invalidate()源码分析


子没有多大的变化,只是在onCreate()方法中直接调用invalidate()方法,如:
这样做的目的主要是想看看,自己调用View的invalidate()方法会不会触发onDraw()方法。运行一下:
nDraw()方法并没有执行!那么是不是因为没有调用setContentVIew()方法呢?修改onCreate()方法:


再次运行,效果:
说明,只有setContentVIew()方法中的invalidate()方法启了作用,自己调用View的invalidate()方法,mView.invalidate()没启任何作用。但是,在MyView的onDraw()方法中调用invalidate()方法可以循环调用onDraw()方法,类似递归。
分析一下,invalidate()方法的源码吧,在这里也许可以找到答案。


这里可以看到p.invalidateChild(this, r)(看源码只看关键部分,不然你会很晕!),其中p是ViewParent实例对象。ViewParent是一个接口,现在我们关心谁实现了这个接口?
通过千辛万苦的search,终于找到ViewParent的实现类ViewRoot:


那么,看看该类实现的invalidateChild()方法:


关键代码在这儿:
这个方法是向Handler发送消息:


接下来,看看ViewRoot的Handler的handleMessage的实现:


performTraversals()方法,调用ViewRoot的私有方法private void draw(boolean fullRedrawNeeded),在该方法中有句代码很关键:
其实这句代码,就是调用View的draw()方法 ,关键代码:
也就是说,满足这个方法,就会回调onDraw()方法。到此为止,您应该明白,当我们自己调用invalidate()方法时,想使onDraw()方法回调,必须满足条件。
调用关系,请看草图!
我是天王盖地虎的分割线
<b></b>
<b>本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3851955.html,如需转载请自行联系原作者</b>