Android 两个线程 UI线程和非UI线程。而Handler是非UI线程向UI线程传递消息的桥梁。
相同 在与UI线程的通信上,Handler与View,其实最终都做了同样的事情。就是将消息传递在UI线程 的消息队列里,执行一些处理操作。
不同
View.post方法想在非UI线程有效工作。如该方法的注释所说,必须保证该View已经被添加至窗口。
View.post()获取View宽高
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
private void show(){
if(myView.getVisibility()==View.GONE){
myView.setVisibility(View.VISIBLE);
}
myView.post(new Runnable() {
@Override
public void run() {
//对view执行动画
}
});
}
意思是将任务交由attachInfo
中的Handler
处理,保证在UI线程执行。从本质上说,它还是依赖于以Handler、Looper、MessageQueue、Message为基础的异步消息处理机制。相对于新建Handler进行处理更加便捷。因为attachInfo
中的Handler
其实是由该View的ViewRootImpl
提供的,所以post
方法相当于把这个事件添加到了UI 事件队列中。下面举一个常用的例子,比如在onCreate方法中获取某个view的宽高,而直接View#getWidth获取到的值是0。要知道View显示到界面上需要经历onMeasure、onLayout和onDraw三个过程,而View的宽高是在onLayout阶段才能最终确定的,而在Activity#onCreate中并不能保证View已经执行到了onLayout方法,也就是说Activity的声明周期与View的绘制流程并不是一一绑定。那为什么调用post方法就能起作用呢?首先MessageQueue是按顺序处理消息的,而在setContentView()后队列中会包含一条询问是否完成布局的消息,而我们的任务通过View#post方法被添加到队列尾部,保证了在layout结束以后才执行。