Activity本是一个普通的Java类,但是它却可以setContentView(),显示一个界面。而实际上是他的内部持有了一个Window,其实现是一个PhoneWindow对象,他是一个抽象的封装,一系列功能的集合,真正的界面载体是DecorView。
问题1:Activity对象何时创建?
Activity是在应用程序进程中通过反射创造出来的。当客户端要启动一个Activity时,会先告知AMS,AMS这边处理后再通知客户端可以启动Activity了,ActivityThread执行performLaunchActivity(),在该方法中创建出Activity对象,并且调用其Activity的attach()方法,为其配置一个Window对象。在后续的onCreate()方法中,用户设置的View对象就被PhoneWindow添加到DecorView中去了。此时,用户设置的View已经被添加到DecorView中去了,但是,界面却没有显示出来,客户端也无法响应触摸按键消息。
问题2:Activity中的界面是怎么显示的?
当Activity对象被创建出来后,ActivityThread会接着执行handleResumeActivity()方法。在该方法中,调用WindowManagerGlobal的addView()方法。
void addView(){
root=new ViewRootImpl(); //DecorView和Window之间的沟通桥梁
//......
try{
root.setView();
}
}
void setView(){
//......
requestLayout(); //发起第一次布局请求
//......
mWindowSession.addToDisplay() //告知WMS,界面已经显示
}
当setView()方法执行完毕后,WMS中已经有了该Window的信息,可以将触摸消息等事件通过Binder传递给ViewRootImpl的内部类W,W进而告知ViewRootImpl,然后再发送消息到UI队列,从而在UI线程中处理消息。
ActivityThread中的ApplicationThread(Binder类)和AMS通信。比如启动Activity,销毁Activity等。
ViewRootImpl中的W(Binder类)和WMS通信。比如MOVE事件等等。
当客户端创建出一个Binder类,系统会自动创建一个Binder线程,用户等待异步的消息,不可能在UI线程中等待异步消息。