Android Activity View加载与绘制流程深入刨析源码 1.App的启动流程,从startActivity到Activity被创建. 这个流程主要是ActivityThread和ActivityManagerService之间通过binder进行通信来完成. ActivityThread可以拿到AMS 的BinderProxy.AMS可以拿到ActivityThread的BinderProxy Applicati
1.App的启动流程,从startActivity到Activity被创建。
这个流程主要是ActivityThread和ActivityManagerService之间通过binder进行通信来完成。
ActivityThread可以拿到AMS 的BinderProxy。AMS可以拿到ActivityThread的BinderProxy ApplicationThread。这样双方就可以互相通讯了。
当ApplicationThread 接收到AMS的Binder调用后,会通过handler机制来执行对应的操作。
可以这样说handler和binder是android framework重要的两块基石。
而Activity的创建就是在ActivityThread中调用handleLaunchActivity方法实现。
2.接下来看performLaunchActivity。创建一个Activity。
如果Activity创建成功,先调用activity.attach(),在这个方法中,创建了Activity的PhoneWindow实例。
然后mInstrumentation.callActivityOnCreate,调用了Activity的onCreate生命周期方法。
3.setContentView,布局加载流程:
在Activity.onCreate方法中,我们通过setContentView(R.layout.activity_main);就能在界面显示,那android是怎么做到的?
1)调用installDecor(),初始化Decorview和mContentParent。
2)mLayoutInflater.inflate(),将布局文件,解析成android中对应的View。
先看installDecor(),通过generateDecor() new了一个DecoView实例并赋值给了mDecor,
mDecor是PhoneView的一个变量。
通过generateLayout(decor) 加载了一个系统的layout文件,在android.jar--res--layout目录下。
在mDecor.onResourcesLoaded方法中加载了这个布局,并添加到了mDecor中。
DecorView继承自FrameLayout,是一个真正的view。
然后通过findViewbyid,找到了一个ViewGoup,可以看下面的布局文件。
ID_ANDROID_CONTENT = com.android.internal.R.id.content; ,并把这个返回出去了。
这个view 就installDecor()方法中的mContentParent()
总结:至此 installDecor();已经完成。主要是创建了mDecorView,并加载了一个系统的布局,R.layout.screen_simple,
将加载得到的View添加到了mDecorView中,并findViewById(R.id.content)的到的View赋值给了mParentContent。
回到setContentView中看第二行代码:
layoutResID 就是传入的布局文件id,mContentParent就是加载的系统的布局文件中id为“content”的view
mLayoutInflater.inflate(layoutResID, mContentParent);
至此上面的关系可以总结为:
Activity-->PhoneWindow-->mDecorView-->addView(R.layout.screen.simple)-->
R.id.content-->mParentContent-->addView(R.layout.activity.main)
我们自己写的layout已经添加到了系统的DecorView中。
4.我们知道View有三个重要的方法onMeasure,onLayout,onDraw,
那这些方法是在哪里调用的?我们创建的View是如何添加到屏幕上的呢?
回到handleLaunchActivity方法中,还有一个handleResumeActivity,通过performResumeActivity 会执行Activity的onResume生命周期方法。
执行完onResume方法后:
wm.addView(decor, l);
将Activity的DecorView添加到了wm中。
ViewManager wm = a.getWindowManager();
ViewManager 是一个抽象类,实例是WindowManagerImpl。
在WindowManagerImpl中通过单例模式获取了一个WindowManagerGlobal对象。
既然是单例模式获取的对象,也就在一个进程,ActivityThread 主进程中 只有一个实例。
在WindowManagerGlobal中创建了一个ViewRootImpl对象。这是很重要的一个对象。
将传进来的DecorView设置在了root中,root.setView(view, wparams, panelParentView);
在setView()方法中有两句很重要的代码。
requestLayout();
res = mWindowSession.addToDisplay()
1) requestLayout()请求布局,调用者行代码会执行view的measue,layou,draw方法。
checkThread这有一个很重要的知识点,为啥子线程不能修改主线程创建的view?
在scheduleTraversals方法中。通过mChoreographer编舞者对象,最后执行了mTraversalRunnable中的方法。这块代码在消息屏障文章中,详细分解。
在TraversalRunnable中执行了doTraversal()方法。在这里调用了三个重要的方法
performMeasure(),performLayout(),performDraw()。
这也就是为什么View的绘制流程是先调用onMeasure,onLayout,后调用onDraw的原因。
并且这些写方法都是在onResume执行才调用的。所以,这就是我们想拿到View的宽高,在onResume之前拿不到的原因。
到此这篇关于Android Activity View加载与绘制流程深入刨析源码的文章就介绍到这了,更多相关Android Activity View内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!