我是靠谱客的博主 无语糖豆,最近开发中收集的这篇文章主要介绍android中view源码,结合源码,探索Android中的Window与DecorView,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

用心分享,你的 点赞|转发分享 是对我最大的鼓励,关注以及时获取最新推文。

Android中View可以说是最为重要的几个地方之一,包括事件分发,测量,绘制等等,都是非常常见的情况。那么我们要想好好掌握这些知识,就得深入了解Andorid整个View从开始到完成所经历的一系列工作。

本文分析的源代码均来自Android API 24。

1. Activity 和 Window

在Android中,Activity并不负责视图控制,它只是控制生命周期和处理事件,真正控制视图的是Window。一个Activity包含了一个Window,Window才是真正代表一个窗口,也就是说Activity可以没有Window,那就和Service没多大差别了。

Window第一次出现在Activity中是在ActivityThread调用Activity的attach()方法时,通过PolicyManager创建window,实现callback方法,所以,当window接收到外界状态改变时,会调用activity的方法:

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,

NonConfigurationInstanceslastNonConfigurationInstances,

Configuration config, String referrer,IVoiceInteractor voiceInteractor) {

//....

//在这里直接new一个Window

mWindow = PolicyManager.makeNewWindow(this);//设置回调接口,当window接收系统发送给它的例如键盘和触摸屏事件,就可以通知Activity,Activity做出相应的处理

mWindow.setCallback(this);

.....

//设置窗口管理器

mWindow.setWindowManager(

(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),

mToken, mComponent.flattenToString(),

(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

.....

}复制代码

在attach()中,Activity新建一个PhoneWindow实例作为成员变量,这是Window的唯一一个子类。然后设置mWindow的WindowManager。

2. DecorView

首先简单介绍一下DecorView,这里引用任玉刚大神的《Android开发艺术探索》书中的介绍:

它是一个顶级View,内部会包含一个竖直方向的LinearLayout,这个LinearLayout有上下两部分,分为titlebar和contentParent两个子元素,contentParent的id是content,而我们自定义的Activity的布局就是contentParent里面的一个子元素。View层的所有事件都要先经过DecorView后才传递给我们的View。

那么DecorView是何时出现的呢??又是如何和window产生联系呢??

188fea46ce775d1ce4ac36a185b8ae93.png

首先,如上图我们可以看到Activity中包含了 Window、DecorView、WindowManager 等成员变量,那么我们就从Activity的创建过程中去逐步寻找它们。

首先在Activity中的onCreate方法中我们都会写一句setContentView的方法调用,将我们自定义的Activity布局传入。那么我们跟进该方法去看一下具体实现。

8c2189a11b55497e5117b33875907ab7.png

通过getWindow来获取成员变量mWindow。

5ed6d9f5ab1f5006cd1938a47cce9c63.png

然后调用window的setContentView()方法。该方法来进行我们Activity的布局设置。然后又接着调用了initWindowDecorActionBar()方法来进行对ActionBar的新建和初始化。我们暂时不管该方法。

mWindow类型是Window,是一个接口,而在安卓中实现Window接口的实现类只有PhoneWindow,所以进入PhoneWindow查看setContentView()方法的具体实现。先上源代码:

181b4298a5611782b3a85a474107b1d4.png

首先会在上图标记1处判断mContentParent是否为空,如果为空,会执行installDecor()方法,那么mContentParent是什么呢?

8de8d5d8e23d31acc22a381f0af0d9b9.png

通过定义可以看出,mContentParent是一个ViewGroup类型的变量,它是Activity的一个成员变量。我们所写的setContetView()所设置的布局文件就加到这个视图中。根据官方解释它可能是mDecor自身,也可能是mDecor的子View。

继续回到setContentView中看代码,如果mContentParent为空,那么会执行installDecor()方法,跟进这个方法,顾名思义,新建DecorView。下面给出源代码:

ca3f9f097795ac2ef463d9028f4e9717.png

在installDecor方法中标注1处,如果mDecor为空(mDecor是Window持有的一个成员变量,指的就是DecorView),那么在 generateDecor()中去实例化新建DecorView,我们继续跟进generateDecor()查看源代码:

529416215e513acc8016c65fdf6ee441.png

在这里前面一段代码都是初始化所需要的context,最后返回一个实例化的DecorView()。在DecorView构造方法中进行初始化工作。

07735657cc123ec0a505b1afd2d26360.png

上图是DecorView的一些初始化工作,就不再展开,有兴趣的同志们可以研究。

返回到installDecor()方法中继续往下,到标记处2,会判断mContentParent是否为空,如果为空,通过 generateLayout()来将我们具体的布局加载到DecorView中。跟入 generateLayout()方法查看源代码(由于方法中代码过长不便于截图,我贴出关键代码):

...//代码前面都是在获取主题相关

//在这个方法里将mContentParent的布局转换并添加到DecorVew中

//具体代码在下一个代码框中

mDecor.onResourcesLoaded(mLayoutInflater,layoutResource);

//contentParent就是root的父布局。

ViewGroup contentParent =(ViewGroup)findViewById(ID_ANDROID_CONTENT);

return contentParent;复制代码

//将mContentParent布局转换为View

final View root = inflater.inflate(layoutResource,null);

//将mContentParent加入到DecorView中

mDecor.addView(root,newViewGroup.MarginLayoutParams(MATCH_PARENT,MATCH_PARENT));

//mContentRoot就是mContentParent视图

mContentRoot = (ViewGroup)root;复制代码

至此generateLayout()方法分析完毕,返回contentParent变量,赋值给mContentParent成员变量。

随后上述步骤也是installDecor()方法的主要代码,因此继续返回到setContentView方法继续查看(把setContentView的图继续贴下来避免返回去翻图):

181b4298a5611782b3a85a474107b1d4.png

图中标注处2的代码,则是将我们的自定义布局加入到mContentParent(也就是id为R.id.content)布局中。最后标记处3则是通过回调来通知ActivityContent已经发生了变化,由Activity来做出相应的处理。

3. DecorView 和 Window

至此已经setContentView已经完成,DecorView也已经新建,我们自定义布局也加入到mContentParent布局中,但是此时mDecorView还没有被WindowManager正式添加到Window中。因此Window此时还无法接受外界的信息,也无法提供具体的功能。

所以在activity中的onResume()方法中调用了makeVisible()方法来进行添加,同时也是把Window加入到WindowManager中

void makeVisible() {

if (!mWindowAdded) {

ViewManager wm = getWindowManager(); //获得WindowManager(WindowManager extends ViewManager)

wm.addView(mDecor, getWindow().getAttributes()); //将DecorView加入到Window中

mWindowAdded = true;

}

mDecor.setVisibility(View.VISIBLE);

}复制代码

至此整个decorView的加载过程和Activity的Window创建过程已经完成,Decor将会 显示出来呈现在手机屏幕上。

原文:初探Android中Window与DecorView

签约作者:晨心w

END

1. 关注并回复 [加群], 邀请你进Android技术群

2. 公众号开放投稿:

你有好的文章,我有平台,那么~

9638b39251d99b717c5bfa760e100b9f.png

一位6年软件工程师的总结与反思

iOS 用户赞赏通道 [请备注姓名]

一个 有价值、有温度 的公众号

一位 爱分享、乐助人 的开发者

期待你的关注并一起交流

最后

以上就是无语糖豆为你收集整理的android中view源码,结合源码,探索Android中的Window与DecorView的全部内容,希望文章能够帮你解决android中view源码,结合源码,探索Android中的Window与DecorView所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部