(17/30)活动、窗、DecorView、ViewRoot
牛客高级系列专栏:
安卓(安卓系统开发也要掌握)
- 想通关安卓面试,请看(承诺免费售后答疑):《150道安卓高频面试题目录及答案链接》
- 想通关安卓系统面试,请看:《140道安卓系统Framework面试题目录及答案链接》
- 想进阶安卓开发,请看(承诺免费售后答疑):《Android进阶知识体系解析_15大安卓进阶必备知识点》
- 想了解安卓APP完整开发流程,请看(承诺免费售后答疑):《安卓APP完整开发流程》
- 想掌握安卓App性能优化,请看(承诺免费售后答疑):《安卓性能优化讲解和实战专栏》
- 想掌握Gradle语法和配置,制作Gradle插件,请看(承诺免费售后答疑):《安卓Gradle语法解析和实践大全》
嵌入式
- 想通关嵌入式面试,请看: 《111道嵌入式面试题目录及答案链接》
- 想多掌握几个嵌入式项目,请看:《6个嵌入式项目交流分享(附源码)》
本人是2020年毕业于广东工业大学研究生:许乔丹,有国内大厂CVTE和世界500强企业安卓开发经验,该专栏整理本人对常见安卓高频开发面试题的理解;
网上安卓资料千千万,笔者将继续维护专栏,一杯奶茶价格不止提供答案解析,承诺提供专栏内容免费技术答疑,直接咨询即可。助您提高安卓面试准备效率,为您面试保驾护航!
正文开始⬇
安卓应用开发经常会接触到UI开发,除了对View的绘制流程需要有所了解,对我们目光所及的界面的层级也需要有所了解。Activity、Window、DecorView以及ViewRoot之间到底有什么联系呢?面试官可能会问:
- 请讲述Activity、Window、DecorView以及ViewRoot之间的层级关系⭐⭐⭐⭐⭐
- DecorView什么时候可见?⭐⭐⭐⭐
看完以下的解析,一定可以让面试官眼前一亮。
目录
- 1、Activity、Window、DecorView以及ViewRoot之间的层级关系
- 1.1 Activity
- 1.2 Window
- 1.3 DecorView
- 1.4 ViewRoot
- 2、DecorView源码分析
- 3、DecorView的显示
- 4、ViewRoot
- 5、总结
1、Activity、Window、DecorView以及ViewRoot之间的层级关系
图片可以最直观看出这几个模块之间的层次关系。
1.1 Activity
我们都知道可以Activity来创建可以触摸的视图界面,但其实Activity并不负责视图的控制。真正控制视图界面的是Window。每一个Activity包含一个Window。Activity主要负责视图界面的统筹,如添加、显示等,并通过一些特定的方法来和Window、View做交互。
1.2 Window
Window意味“窗口”,是视图界面真正的承载器。Window是一个接口类,实际的窗口是PhoneWindow类,该类内部有一个内部类DecorView。就可以通过创建DecorView来加载布局xml文件。
1.3 DecorView
DecorView是FrameLayout类的子类,通常认为DecorView是Android视图树的根节点,也就是最顶层的View。DecorView内部包含一个LinearLayout,在这个LinearLayout里面有上下三个部分,上面是个ViewStub,延迟加载的视图(应该是设置ActionBar,根据Theme设置),中间的是TitleView,根据Activity的主题设置的,有的布局就没有这个标题栏,最下面的是ContentViews,这是最重要的一部分,我们平时自定义的布局文件通过setContentView()方法加载,其实就是加载到这个ContentViews里面,成为其唯一的子View。Window 通过WindowManager将DecorView加载其中,并将DecorView交给ViewRoot,进行视图绘制以及其他交互。通过一个实际的DecorView文件加深理解:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:fitsSystemWindows="true"
android:orientation="vertical">
<!-- Popout bar for action modes -->
<ViewStub
android:id="@+id/action_mode_bar_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:theme="?attr/actionBarTheme" />
<FrameLayout
style="?android:attr/windowTitleBackgroundStyle"
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize">
<TextView
android:id="@android:id/title"
style="?android:attr/windowTitleStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:fadingEdge="horizontal"
android:gravity="center_vertical" />
</FrameLayout>
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foreground="?android:attr/windowContentOverlay"
android:foregroundGravity="fill_horizontal|top" />
</LinearLayout>
1.4 ViewRoot
ViewRoot作用非常重大。所有View绘制、触摸事件分发、界面刷新等都是通过它来执行或传递的。ViewRoot对应ViewRootImpl类,它是连接WindowManagerService和DecorView的纽带。
ViewRoot并不属于View树的一份子。从源码实现上来看,它既非View的子类,也非View的父类,但是,它实现了ViewParent接口,这让它可以作为View的名义上的父视图。RootView继承了Handler类,可以接收事件并分发,Android的所有触屏事件、按键事件、界面刷新等事件都是通过ViewRoot进行分发的。
2、DecorView源码分析
从上面的介绍可以看出DecorView的重要地位,这一节,通过阅读源码,进一步弄清楚:
- Activity、Window、DecorView以及ViewRoot之间的层级嵌套关系;
- DecorView的创建和显示;
为了读者可以更加完整的了解上面两个问题,我们从handleLaunchActivity()方法开始追溯,该方法是Activity启动的本地操作入口,完成整个Activity的启动流程。 以下源码来自Android9.0.0/frameworks/base/core/java/android/app/ActivityThread.java:
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent); // 1
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
}
...
return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback); // 2
...
}
在Acitivy的创建流程有如下调用关系:
handleLaunchActivity()-> [注释1]performLaunchActivity()-> [注释2]activity.attach()
继续跟踪源码就到了activity.attach(),其源码在/frameworks/base/core/java/android/app/Activity.java:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstan
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
#提供免费售后答疑!!花一杯奶茶的钱获得安卓面试答疑服务,稳赚不赔# Android发展已经很多年,安卓资料网上千千万,本专栏免费提供专栏内容技术答疑!!私聊当天必回。在阅读过程或者其他安卓学习过程有疑问,都非常欢迎私聊交流。