前言:本篇文章通过对APP启动过程(从点击图标—>Activity可见)的分析,来搞懂这一过程遇到的几个重要的知识点,以解心中的疑惑,同时通过对整个过程的分析,让孤立的知识点串联起来,有个更好的理解和掌握。
程序入口——ActivityThread.main()
Android程序的入口是ActivityThread
类中的main()
方法,就是当我们点击一个APP图标时,系统最开始执行的地方。以后当被人问到这个问题时,就不要回答“Activity的onCreate()方法”了。
执行的操作
1、调用prepareMainLooper()
在主线程中创建一个消息队列。
2、创建ActivityThread
对象。
3、创建Handler
对象。
4、创建ApplicationThread
对象
过程讲解
1、ActivityThread:每个应用程序都对应着一个ActivityThread
实例,其中的main()
方法是程序的入口,通过一系列的初始化操作,它最终的操作是通过调用ActivityThread.handleMessage()
方法接收系统传来的消息,创建Activity。
Q:消息是由谁传递过来的?请看2.
2、ApplicationThread:每个应用程序对应着一个ApplicationThread
对象,它是一个Binder对象,Binder是用来进行IPC(进程间的通信)操作的。所以它的作用是接收AMS传来的远程消息,例如AMS发送star某个Activity,然后ApplicationThread
再通过Handler(线程间的通信)传递给ActivityThread
,ActivityThread
调用handleMessage()
方法来处理这个消息,进行创建Activity的操作。由此可见,ApplicationThread
是ActivityThread
与AMS之间信息传递的桥梁。
Q:AMS又是啥?请看3.
3、AMS(ActivityManagerService):AMS是Android中的一个核心服务,主要负责系统中四大组建(有的文章说不包括BroadcastReceiver)的启动、切换、调度等工作。所以当我们点击打开一个APP时,AMS会向ApplicationThread
发送请求开启一个Activity,然后由ApplicationThread
传递给ActivityThread
来进行具体操作,上面我们已经提到。
现在我们已经知道了消息传递的大体流程,当ActivityThread
收到AMS传来的启动一个Activity的消息后,就会调用handleMessage()
方法创建指定的Activity,具体如何做的呢?
从代码可以看出,它调用了handleLaunchActivity()
方法,那我们进入看看。
该方法又调用了performLaunchActivity()
方法来返回一个Activity,想必Activity应该就是在这个函数中创建完成的了。此方法执行后,又调用了handleResumeActivity()
方法,我们先看performLaunchActivity()
做了什么。
performLaunchActivity()
performLaunchActivity()做了哪些事
1、从ActivityClientRecord
中得到接下来要启动Activity的ComponentName
信息。
2、从ActivityClientRecord
中得到接下来要启动Activity的信息
通过Instrumentation.newActivity
方法,利用LoadedApk的类加载器尝试创建Activity的对象。
3、通过LoadedApk.makeApplication
方法尝试创建Application对象,在这个方法里会通过`Class.newInstance()
方法创建Application的对象,并且它的onCreate
方法也是在此时被调用的。
4、为Activity创建ContextImpl的
对象,调用Activity.attach()
方法。
5、调用Activity.setTheme
方法,如果Activity申明时指定了theme的话。
6、调用Activity.onCreate()
方法,然后是onStart()
方法,如果之前有保存的状态那么还会调用onRestoreInstanceState()
方法,最后调用onPostCreate()
方法,至此整个launch过程算是结束了。
进入onCreate()方法
下面终于进入到onCreate()
方法了,首要执行的就是setContentView(R.layout.main)
,这个方法的目的是设置我们在xml文件中定义的布局,我们进入这个方法看看。
该方法中调用了mWindow()
的setContentView()
方法,因为我们可以从代码中看出getWindow()
返回的是mWindow
,mWindow
是Window
类型的,而Window
是一个抽象类,它的实现类是PhoneWindow
。所以, getWindow().setContentView()
方法就是调用的PhoneWindow
的setContentView()
方法,然后我们进入看看。
首先,判断mContentParent
是否为空,为空则执行installDecor()
。mContentParent
是什么?从代码中的注释可以看到说“mContentParent是mDecor本身或者是mDecor的一个子元素
”,mDcor
是DecorView
的实例,大家可能还不明白,所以要先搞清DecorView
是什么,然后我们继续往下看,看看installDecor()
方法做了什么。
从代码可以看出,它调用了generateDecor()
方法:
好了,可以看出,这里实例化出了一个DecorView
,那DecorView
是什么呢?
由代码可见,DecorView
继承自FrameLayout
,而FrameLayout
继承自ViewGroup
,所以DecorView
是一个ViewGroup
。其实,它是ViewTree的最顶层的一个View,它是一个FrameLayout
布局,代表了整个应用的界面,由TitlView和ContentView两个子元素,而ContentView则是上面提到的mContentParent
,那为什么刚才注释里说“mContentParent是mDecor本身或者是mDecor的一个子元素
”呢?我们进入installDecor()
中注释的2号代码:
由以上代码可以看出:首先根据设置的主题样式来设置DecorView
的风格,比如说有没有titlebar之类的,接着为DecorView
添加子View,而这里的子View则是上面提到的mContentParent
,如果上面设置了FEATURE_NO_ACTIONBAR
,那么DecorView
就只有mContentParent
一个子View,这也解释了上面的疑问:mContentParent是DecorView本身或者是DecorView的一个子元素。
handleResumeActivity()
performLaunchActivity()
执行完了之后,接着会执行handleResumeActivity()
方法,看看源码会执行哪些操作:
该方法内部会先获得与该Activity关联的几个对象:
1、WIndow
对象
2、DecorView
对象
3、WindowManager
对象,它的实现类是WIndowManagerImpl
接着会调用WIndowManagerImpl
的addView()
方法:
这里面又调用了mGlobal
的addView()
方法,mGlobal
是WindowManagerGlobal
的一个实例,我们进入该方法:
1、首先实例化一个ViewRootImpl
类。
2、然后调用ViewRootImpl
的setView()
方法,把DecorView
作为参数传进去。在这里,ViewRootImpl
是WMS
与DecorView
之间沟通的一个桥梁。
3、在这个方法内部,会通过跨进程的方式向WMS(WindowManagerService)发起一个调用,从而将DecorView最终添加到Window上。
4、最后通过WMS调用ViewRootImpl.performTraverals
方法开始View的测量、布局、绘制流程。这个下一篇再讲解。
通过前面的讲解,我们可以如此总结:
Android应用程序窗口 = Activity + PhoneWindow + DecorView
DecorView = TitleView + ContentView(layout.xml文件)
画图表示如下(每一层的大小都是一样的,是覆盖关系,这里是为了方便表示出每一层):
参考:
1、http://www.voidcn.com/blog/u012827296/article/p-4991222.html