Android笔记(四)DecorView & ViewRootImpl & Window
来源:互联网 发布:魔龙诀时装进阶数据 编辑:程序博客网 时间:2024/06/07 03:32
这三者之间的关系网络上有很多篇不错的blog。比如这篇。为了让自己更加熟悉View绘制的流程,在这里特意将这三者的关系好好梳理一番。
为了理清这三者的关系,还是先上一张图
- ViewRootImpl是ViewRoot的实现类,ViewRoot不是view,而是整个ViewTree的管理者。
- DecorView是整个ViewTree的根布局视图
- ViewRoot通过在Activity.attach()中将DecorView绑定到Activity对应的Window中,在addView时涉及到跨进程通信
- 这里的跨进程通信主要就是ViewRoot和WMS之间通信,通过传递IWindowSession和IWindow来完成。
按照个人理解,在window起来的时候,先完成的工作是得到一个最初的View,用作最底层的view(或者说放在Window里面作为根view,事实上不存在这种将view放置在window中的说法,因为window只是一个虚拟的窗口),这个view也就是我们通常说的DecorView。得到这个DecorView之后,接下来的工作就是通过addView将这个View呈现出来,这里才会涉及到ViewRootImpl,这样DecorView才算是真正与window绑定在一起了。
Window创建过程
PhoneWindow是Window的实现类,里面几个和DecorView相关的属性
ViewGroup mContentParent;//ViewGroup,也就是我们的R.id.contentTextView mTitleView;//也就是我们的R.id.titleDecorContentParent mDecorContentParent; //接口,用来设置一些window的属性
我们以Activity的启动创建Window为例来进行说明,除此之外Dialog、Toast等在启动时也会创建Window。
Activity的启动较为复杂,后面会专门花时间来讲解。Acitvity的启动最终都会由ActivityThread的performLaunchActivity()来完成启动。
...//通过反射创建AcitivityClassLoader cl = r.packageInfo.getClassLoader();activity=mInstrumentation.newActivity(cl,component.getClassName(),r.intent);...//在activity中创建window对象activity.attach(appContext,this,getInstrumentation(),r.token,..window);
在Activity中的attach方法中,完成了 Activity中window的创建,而且设置相关回调接口,包括我们常见的onAttachedToWindow、dispatchTouchEvent()等。此外还将ActivityThread中的信息传递到Activity
attachBaseContext();mWindow = new PhoneWindow(this,window);mWindow.setCallback(this);...mUiThread = Thread.currentThread();mMainThread = aThread;mInstrumentation = instr;mToken = token;
这样我们就在启动一个Acitivity时,创建好了一个window。但此时window中啥都没有,我们在activity中解析xml文件,添加view到window是怎样做到的呢。首先,我们需要想到的是,一个window对应一个根view。这个view就是DecorView。添加view的过程在setContentView()中完成。包括创建DecorView,添加view,显示view。
Activity中的setContentView()方法
public void setContentView(View view,ViewGroup.LayoutParams params){ getWindow().setContentView(view,params); initWindowDecorActionBar();}
Window的具体实现是PhoneWindow。因此我们只需要看PhoneWindow中的相关逻辑。
在PhoneWindow的setContentView方法中,如果没有DecorView,那就创建一个。
//mContentParent是DecorView的子布局ViewGroup,也就是我们的R.id.contentif(mContentParent = null){ installDecor();}
然后解析我们的xml或者加载view到mContentParent上,其中mLayoutInflater在PhoneWindow构造时被赋值
mLayoutInflater.inflate(layoutResID,mContentParent);
完成这些后,还只是完成了Window的创建以及与Activity的绑定,还没有将Window添加到WMS中,所以还不会显示出来(mDecorView还没有被wms识别)。显示通过ActivityThread中的handleResumeActivity()来完成
if(a.mVisibleFromClient && !a.mWindowAdded){ a.mWindowAdded = true; wm.addView(decor,l);}
DecorView介绍
DecorView为顶级View,事实上也具有普通View的特性,其布局为FrameLayout布局。以前的版本中,DecorView是PhoneWindow的内部类,PhoneWindow是Window抽象类的唯一实现,足以表示两者的关系。不过最新的版本中DecorView已经独立成了一个普通类,里面有三个最重要的属性
mWindow 窗口,后续加载content内容用到
mContentRoot 用于放置R.id.content的ViewGroup
- mDecorCaptionView 和多窗口相关
这样我们就清楚地知道了DecorView里面的布局。对于普通Activity这两这个子View(mContentRoot mDecorCaptionView都有,对于没有多窗口的,则只有mContentRoot)。将view添加到DecorView主要是靠下面这个方法onResourceLoaded()
layoutResource为我们传进来的R.layout.xxx资源。先创建mDecorCaptionView
第1992行清楚地向我们显示了DecorCaptionView的加载。再回到上一幅图,加载完DecorCaptionView之后就加载mContentRoot(01919行所示),然后需要做的事情就是先判断mDecorCaptionView是否为空,如果为空则只把mContentRoot直接添加到DecorView中。如果不为空则先把mDecorCaptionView添加到DecorView,然后把mContentRoot添加到mDecorCaptionView中。大致的图如下
到这里我们就完成了整个DecorView的构造,下面就要进行其放置过程。事实上,DecorView的构造是在PhoneWindow中进行的。大概流程为:Activity中的setContentView最终会调用到PhoneWindow中的setContentView。在这个方法中首先就要判断DecorView是否存在,不存在就创建。DecorView的添加是在ActivityThread中的handlerResumeActivity添加的。
wm.addView(decor,l);
从这儿就可以看出Activity中onCreate在onResume方法之前,先创建DecorView,然后放置DecorView。WindowManager是一个抽象类,我们需要在其实现类WindowManagerImpl中去查看addview方法。结果发现真正调用的是WindowManagerGlobal类中的addView方法
也就是说,RootViewImpl和DecorView上下文一一对应。
从上面可以看出真正的添加DecorView操作是在这儿,调用ViewRootImpl.setView方法,在这个方法内部,会通过跨进程的方式向WMS(WindowManagerService)发起一个调用,从而将DecorView最终添加到Window上,在这个过程中,ViewRootImpl、DecorView和WMS会彼此关联,至于详细过程这里不展开来说了。最后通过WMS调用ViewRootImpl#performTraverals方法开始View的测量、布局、绘制流程。
后面将会讲解ViewTree遍历的时机
- Android笔记(四)DecorView & ViewRootImpl & Window
- android发现之旅之ViewRootImpl,Activity,Window,DecorView之间的关系
- Android Window PhoneWindow DecorView
- 浅谈DecorView与ViewRootImpl
- ViewRootImpl 和 DecorView 分析
- Android View源码解读:浅谈DecorView与ViewRootImpl
- Android View源码解读:浅谈DecorView与ViewRootImpl
- Android应用层View绘制流程之DecorView与ViewRootImpl
- Android View源码解读:浅谈DecorView与ViewRootImpl
- Android View源码解读:浅谈DecorView与ViewRootImpl
- Android View源码解读:浅谈DecorView与ViewRootImpl
- 初探Android中Window与DecorView
- Activity的Window创建及DecorView的添加(Android开发艺术探索学习笔记)
- Android ViewRootImpl Choreographer SurfaceFlinger 学习笔记
- Android视图框架Activity,Window,View,ViewRootImpl理解
- has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView
- has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView
- Android中Activity, View,Window,DecorView之间的关系
- UVALive2203 UVa10042 Smith Numbers【质因数分解+素数判定+数位之和】
- Google I/O 2017
- kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
- Spring MVC通过MultipartResolver实现单文件,多文件上传的详细讲解。
- Hibernate工作原理
- Android笔记(四)DecorView & ViewRootImpl & Window
- Spring中的事务管理
- java 保留小数的四种方法
- Hibernate有哪几种查询数据的方式
- springMVC-笔记001-mvc配置文件
- 数据结构.单链表
- vb.net 教程 5-16 图像处理之ImageAttributes 类1 伽玛、阈值和颜色替换
- Java NIO 总结
- Spring整合javamail异常: