从源码的角度浅谈Activity、Window、View之间的关系

简介:

序言

很多人都会用Activity、Window、View,但是你知道他们是怎样加载出来并呈现在你眼前的吗?你知道他们之间有着鲜为人知的关系吗?

讲个很简单的例子,这一天天气甚好,小明外出写生,小明背了一包东西,画板啊,纸啊,笔啊什么的,然后小明找了一处风景甚好的地方,从包里拿出画板,纸,笔然后开始画画,不一会儿小明就画完了一幅风景图。在这个例子当中,画板就好比Activity,纸就好比Window,而笔就是View,我们所看到的就是这幅画,是通过笔一点一点画出来的,在哪里画呢?当然是纸上了,而最终承载这幅画的东西就是画板了。这么说可能不太生动,下面,我们从源码的角度来看看这三者的关系。

Activity的创建过程

我们都知道,Activity启动的时候是从ActivityThread中的Handler中发起的,然后经过handlerLauncher等一系列方法,如果还不知道的话可以去参考我之前写的:

https://github.com/24Kshign/Android-Knowledge/blob/a8b38bf4765df13fee3a573249a1dc472f3a7e6c/Android%E6%BA%90%E7%A0%81%E7%9B%B8%E5%85%B3/Activity%E7%9A%84%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B.md

1ActivityThread类:
2
3private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
4
5    ...
6    WindowManagerGlobal.initialize();
7    Activity a = performLaunchActivity(r, customIntent);
8    ...
9}

在这里先调用了WindowManagerGlobal中的初始化方法初始化了WindowManagerService,看名字大概就能知道这是一个WindowManager的服务,通过这个服务可以对页面进行操作;然后通过调用performLaunchActivity方法生成了一个Activity。

Window的创建过程

上面通过performLaunchActivity方法生成了一个Activity,我们来看看是怎样生成的:

 1ActivityThread类:
2
3private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent{
4
5    ...
6    Activity activity = null;
7    try {
8        activity = mInstrumentation.newActivity(cl, 
9                component.getClassName(), r.intent);
10    } catch (Exception e) {
11        ...
12    }
13    ...
14
15    if (activity != null) {
16        activity.attach(appContext, this, getInstrumentation(), r.token,
17                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
18                        r.embeddedID, r.lastNonConfigurationInstances, config,
19                        r.referrer, r.voiceInteractor, window, r.configCallback);
20    }
21
22    ...
23}

在这个方法中,通过newActivity这个方法(反射)来生成了一个Activity,生成好了Activity之后就调用Activity中的attach方法,来看一下这个方法里面干了些什么:

 1final void attach(Context context, ActivityThread aThread,
2            Instrumentation instr, IBinder token, int ident,
3            Application application, Intent intent, ActivityInfo info,
4            CharSequence title, Activity parent, String id,
5            NonConfigurationInstances lastNonConfigurationInstances,
6            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
7            Window window, ActivityConfigCallback activityConfigCallback) {
8
9        mWindow = new PhoneWindow(thiswindow, activityConfigCallback);
10        mWindow.setWindowControllerCallback(this);
11        mWindow.setCallback(this);
12        mWindow.setOnWindowDismissedCallback(this);
13        mWindow.getLayoutInflater().setPrivateFactory(this);
14        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
15            mWindow.setSoftInputMode(info.softInputMode);
16        }
17        if (info.uiOptions != 0) {
18            mWindow.setUiOptions(info.uiOptions);
19        }           
20}

果然,在Activityattach方法中创建了一个Window,这个Window就是我们经常听到的PhoneWindow

View的创建过程

我们大胆的猜测一下,View应该是被添加到Window中的,那么我们来看一下,到底是怎样添加的呢?上面说到在handlerLauncher中调用了performLaunchActivity方法,源码中还调用了handleResumeActivity方法,这个方法是在生命周期onCreate之后,onResume之前调用的,我们来看一下在这个方法中干了些什么:

 1final void handleResumeActivity(IBinder token,
2            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
3
4    ...
5    r = performResumeActivity(token, clearHide, reason);
6    ...
7    if (r.window == null && !a.mFinished && willBeVisible) {
8         r.window = r.activity.getWindow();
9         View decor = r.window.getDecorView();
10         decor.setVisibility(View.INVISIBLE);
11         ViewManager wm = a.getWindowManager();
12         WindowManager.LayoutParams l = r.window.getAttributes();
13         a.mDecor = decor;
14
15         ...
16         wm.addView(decor, l);
17         ...
18    }           
19}

这里会先获取一个WindowDecorView,然后拿到ViewManagerWindowManager的父类),然后调用addView方法,ViewManagerWindowManager都是接口,那么我们只要到他的实现类WindowManagerImpl中去找addView方法就可以了:

1    @Override
2    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params
{
3        applyDefaultToken(params);
4        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
5    }

这个mGlobal就是我们之前的WindowManagerGlobal,看到这里相信大家应该有点眉目了吧,最终是由这货负责把DecorView添加到Window中,在WindowManagerGlobal中的addView方法中还会初始化ViewRootImpl,有兴趣的可以自行看源码了解一下

XML中的View是如何添加到DecorView中的这个也不在这里分析了,可以参考我之前写的:

https://github.com/24Kshign/Android-Knowledge/blob/a8b38bf4765df13fee3a573249a1dc472f3a7e6c/Android%E6%BA%90%E7%A0%81%E7%9B%B8%E5%85%B3/setContentView%E6%BA%90%E7%A0%81.md

总结

啥也不说了,上图

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy= e7813f549b4dc165d0a72dfab8647200e58f0dfa


原文发布时间为:2018-09-26
本文作者:24K纯帅豆
本文来自云栖社区合作伙伴“IT先森养成记”,了解相关信息可以关注“IT先森养成记”。
相关文章
|
Java API Kotlin
教你用更好的方式在Activity或Fragment之间传递以及返回数据
教你用更好的方式在Activity或Fragment之间传递以及返回数据
263 0
教你用更好的方式在Activity或Fragment之间传递以及返回数据
|
前端开发 容器
View的测量、布局和绘制过程中父View(当前View)和子View的先后顺序
View的测量、布局和绘制过程中,到底是先测量(布局、绘制)父View,还是先测量子View,这篇文章会从源码角度给出答案。
|
设计模式 缓存 前端开发
理清Activity、View及Window之间关系
理清Activity、View及Window之间关系
|
缓存 Android开发
Android 深入了解 Window 、Activity、 View 三者关系(下)
addView 成功有一个标志就是能够接收触屏事件,通过对 setContentView 流程的分析,可以看出添加 View 的操作实质上是 PhoneWindow 在全盘操作,背后负责人是 WMS,反之 Activity 自始至终没什么参与感。但是我们也知道当触屏事件发生之后,Touch 事件首先是被传入到 Activity,然后才被下发到布局中的 ViewGroup 或者 View(Touch事件分发 了解一下)。那么 Touch 事件是如何传递到 Activity 上的呢?
213 0
|
XML 开发工具 Android开发
Android 深入了解 Window 、Activity、 View 三者关系(上)
Window、Activity、View都经常用到,但三者关系还是没有系统的理清,今天咱们就开始整理整理这三者的关系: Window:顶级窗口外观和行为策略的 抽象基类 。唯一实现是 PhoneWindow类。 Activity:四大组件之一,它提供一个界面让用户点击和各种滑动操作。 View:代表用户界面组件的基本构建块,UI 组件。
228 0
Android 深入了解 Window 、Activity、 View 三者关系(上)
DHL
|
算法 安全 Java
|
Java Android开发
【JetPack】为现有 Android 项目配置视图绑定 ( ViewBinding ) 模块 ( 视图绑定不影响传统布局操作 | 视图绑定类关联 Activity | 视图绑定类本质 )(一)
【JetPack】为现有 Android 项目配置视图绑定 ( ViewBinding ) 模块 ( 视图绑定不影响传统布局操作 | 视图绑定类关联 Activity | 视图绑定类本质 )(一)
185 0
【JetPack】为现有 Android 项目配置视图绑定 ( ViewBinding ) 模块 ( 视图绑定不影响传统布局操作 | 视图绑定类关联 Activity | 视图绑定类本质 )(一)
|
Android开发
【JetPack】为现有 Android 项目配置视图绑定 ( ViewBinding ) 模块 ( 视图绑定不影响传统布局操作 | 视图绑定类关联 Activity | 视图绑定类本质 )(二)
【JetPack】为现有 Android 项目配置视图绑定 ( ViewBinding ) 模块 ( 视图绑定不影响传统布局操作 | 视图绑定类关联 Activity | 视图绑定类本质 )(二)
161 0
|
Android开发
Activity、Window、View三者关系
目录介绍 01.Window,View,子Window 02.什么是Activity 03.什么是Window 04.什么是DecorView 05.什么是View 06.关系结构图 07.Window创建过程 08.
981 0
|
Android开发
Android 开发中的代码片段(2)复制对象之间的属性值
前言 开发中会遇到这样的一个情况,我们得到一个dto对象,里面有几十个属性值,需要将这几十个属性值的N个通过VO传输另外一个地方,一般我们的做法是: 创建VO类,new vo() 对象,通过vo.set(dto.get)的方式不断的设置值。
1094 0