概述
用心分享,你的 点赞|转发分享 是对我最大的鼓励,关注以及时获取最新推文。
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产生联系呢??
首先,如上图我们可以看到Activity中包含了 Window、DecorView、WindowManager 等成员变量,那么我们就从Activity的创建过程中去逐步寻找它们。
首先在Activity中的onCreate方法中我们都会写一句setContentView的方法调用,将我们自定义的Activity布局传入。那么我们跟进该方法去看一下具体实现。
通过getWindow来获取成员变量mWindow。
然后调用window的setContentView()方法。该方法来进行我们Activity的布局设置。然后又接着调用了initWindowDecorActionBar()方法来进行对ActionBar的新建和初始化。我们暂时不管该方法。
mWindow类型是Window,是一个接口,而在安卓中实现Window接口的实现类只有PhoneWindow,所以进入PhoneWindow查看setContentView()方法的具体实现。先上源代码:
首先会在上图标记1处判断mContentParent是否为空,如果为空,会执行installDecor()方法,那么mContentParent是什么呢?
通过定义可以看出,mContentParent是一个ViewGroup类型的变量,它是Activity的一个成员变量。我们所写的setContetView()所设置的布局文件就加到这个视图中。根据官方解释它可能是mDecor自身,也可能是mDecor的子View。
继续回到setContentView中看代码,如果mContentParent为空,那么会执行installDecor()方法,跟进这个方法,顾名思义,新建DecorView。下面给出源代码:
在installDecor方法中标注1处,如果mDecor为空(mDecor是Window持有的一个成员变量,指的就是DecorView),那么在 generateDecor()中去实例化新建DecorView,我们继续跟进generateDecor()查看源代码:
在这里前面一段代码都是初始化所需要的context,最后返回一个实例化的DecorView()。在DecorView构造方法中进行初始化工作。
上图是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的图继续贴下来避免返回去翻图):
图中标注处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. 公众号开放投稿:
你有好的文章,我有平台,那么~
一位6年软件工程师的总结与反思
iOS 用户赞赏通道 [请备注姓名]
一个 有价值、有温度 的公众号
一位 爱分享、乐助人 的开发者
期待你的关注并一起交流
最后
以上就是无语糖豆为你收集整理的android中view源码,结合源码,探索Android中的Window与DecorView的全部内容,希望文章能够帮你解决android中view源码,结合源码,探索Android中的Window与DecorView所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复