[Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法
博客首页:http://www.cnblogs.com/kezhuang/p/
关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下
《[Android FrameWork 6.0源码学习] Window窗口类分析》
本章博客是接着上边那篇博客分析,目的是为了引出分析ViewRootImpl这个类。现在只是分析完了Window和ActivityThread的调用过程
从ActivityThread到WindowManager再到ViewRootImpl这块还属于空白部分,所以要补这篇博客
在上篇博客的末尾提到最后是由WindowManager的addView来请求显示界面,那么我们接着分析
WindowManager这是一个接口,他继承了ViewManager这个接口,所以具有管理View的能力
WindowManager这个实例是通过 Activity.getWindowManager 方法获取的,我们先找到他的实例,在逐渐去看addView函数
public WindowManager getWindowManager() { return mWindowManager; }
Activity中是这样定义的该函数,返回了mWindowManager对像,接下来找一下赋值mWindowManager对象的地方
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, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor) { mWindow = new PhoneWindow(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); }
我们看到在Activity初始化时候调用的attach方法中赋值了mWindowManager方法,但是这个值是从mWindow对象中获取到的,我们进入看一下
public WindowManager getWindowManager() { return mWindowManager; }
在Window中也是这样定义的,返回mWindowManager
public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { mAppToken = appToken; mAppName = appName; mHardwareAccelerated = hardwareAccelerated || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false); if (wm == null) { wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); } mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); }
Window中的mWindowManager是在setWindowManager中创建而来,而这个setWindowManager其实是在Activity的attach方法中调用
可以看到其实就是用的系统服务WindowManager强转成WindowManagerImpl之后又调用了createLocalWindowManager方法得到的对象
public WindowManagerImpl createLocalWindowManager(Window parentWindow) { return new WindowManagerImpl(mDisplay, parentWindow); }
这个方法也很简单,就是new了一下WindowManagerImpl
OK了,到现在可以知道WindowManager的实现类为WindowManagerImpl,那么我们继续分析它实现的addView方法
@Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mDisplay, mParentWindow); }
该方法定义在WindowManagerImpl中,mGlobal为WindowManagerGlobal对象,是一个系统单例对象
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (display == null) { throw new IllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); } else { // If there's no parent, then hardware acceleration for this view is // set from the application's hardware acceleration setting. final Context context = view.getContext(); if (context != null && (context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } } ViewRootImpl root; View panelParentView = null; synchronized (mLock) { // Start watching for system property changes. if (mSystemPropertyUpdater == null) { mSystemPropertyUpdater = new Runnable() { @Override public void run() { synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { mRoots.get(i).loadSystemProperties(); } } } }; SystemProperties.addChangeCallback(mSystemPropertyUpdater); } int index = findViewLocked(view, false); if (index >= 0) { if (mDyingViews.contains(view)) { // Don't wait for MSG_DIE to make it's way through root's queue. mRoots.get(index).doDie(); } else { throw new IllegalStateException("View " + view + " has already been added to the window manager."); } // The previous removeView() had not completed executing. Now it has. } // If this is a panel window, then find the window it is being // attached to for future reference. if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { final int count = mViews.size(); for (int i = 0; i < count; i++) { if (mRoots.get(i).mWindow.asBinder() == wparams.token) { panelParentView = mViews.get(i); } } } //创建了一个新的ViewRootImpl对象出来 root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); //为当前界面保存ViewRootImpl和view还有添加的Layout参数 mViews.add(view); mRoots.add(root); mParams.add(wparams); } // do this last because it fires off messages to start doing things try { //调用ViewRootImpl中的setView方法,准备进行View的重绘流程,并且绘制到界面上 root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { // BadTokenException or InvalidDisplayException, clean up. synchronized (mLock) { final int index = findViewLocked(view, false); if (index >= 0) { removeViewLocked(index, true); } } throw e; } }
这篇博客到这就结束了,接下来我总结下上边的流程
1.Activity初始化的时候创建了一个WindowManager对象(和系统的WindowManager服务还有点区别)
2.利用这个Activity专属的WindowManager对象请求添加一个View到当前界面上
3.WindowManager找到自己的实现类WindowManagerImpl,然后在委托给系统单例类WindowManagerGlobal处理
4.WindowManagerGlobal会创建一个ViewRootImpl对象出来
5.ViewRootImpl对象调用setView方法,然后进行界面重绘最后交给Surface进行界面展示
Ok了,很清晰的分析出了从WindowManager到ViewRootImpl的过程,接下来就可以分析ViewRootImpl.setView和ViewRootImpl的performTraversals方法了
[Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法的更多相关文章
- [Android FrameWork 6.0源码学习] View的重绘过程之Draw
View绘制的三部曲,测量,布局,绘画现在我们分析绘画部分测量和布局 在前两篇文章中已经分析过了.不了解的可以去我的博客里找一下 下面进入正题,开始分析调用以及函数原理 private void pe ...
- [Android FrameWork 6.0源码学习] View的重绘过程之Layout
View绘制的三部曲,测量,布局,绘画现在我们分析布局部分测量部分在上篇文章中已经分析过了.不了解的可以去我的博客里找一下 View的布局和测量一样,都是从ViewRootImpl中发起,ViewRo ...
- [Android FrameWork 6.0源码学习] View的重绘过程
View绘制的三部曲, 测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...
- [Android FrameWork 6.0源码学习] View的重绘ViewRootImpl的setView方法
博客首页:http://www.cnblogs.com/kezhuang/p/ 本篇文章来分析一下WindowManager的后续工作,也就是ViewRootImpl的setView函数的工作 /i* ...
- Android View的重绘过程之WindowManager的addView方法
博客首页:http://www.cnblogs.com/kezhuang/p/ 关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下 <[An ...
- [Android FrameWork 6.0源码学习] LayoutInflater 类分析
LayoutInflater是用来解析XML布局文件,然后生成对象的ViewTree的工具类.是这个工具类的存在,才能让我们写起Layout来那么省劲. 我们接下来进去刨析,看看里边的奥秘 //调用i ...
- [Android FrameWork 6.0源码学习] ViewGroup的addView函数分析
Android中整个的View的组装是采用组合模式. ViewGroup就相当与树根,各种Layout就相当于枝干,各种子View,就相当于树叶. 至于View类.我们就当它是个种子吧.哈哈! Vie ...
- [Android FrameWork 6.0源码学习] Window窗口类分析
了解这一章节,需要先了解LayoutInflater这个工具类,我以前分析过:http://www.cnblogs.com/kezhuang/p/6978783.html Window是Activit ...
- 【Spark2.0源码学习】-1.概述
Spark作为当前主流的分布式计算框架,其高效性.通用性.易用性使其得到广泛的关注,本系列博客不会介绍其原理.安装与使用相关知识,将会从源码角度进行深度分析,理解其背后的设计精髓,以便后续 ...
随机推荐
- 【BZOJ4555】求和(第二类斯特林数,组合数学,NTT)
[BZOJ4555]求和(第二类斯特林数,组合数学,NTT) 题面 BZOJ 题解 推推柿子 \[\sum_{i=0}^n\sum_{j=0}^iS(i,j)·j!·2^j\] \[=\sum_{i= ...
- 【NOIP2012】开车旅行(倍增)
题面 Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i的海拔高度为Hi,城市 ...
- Bzoj4555: [Tjoi2016&Heoi2016]求和
题面 Bzoj Sol 推柿子 因为当\(j>i\)时\(S(i, j)=0\),所以有 \[\sum_{i=0}^{n}\sum_{j=0}^{n}S(i, j)2^j(j!)\] 枚举\(j ...
- POJ1741
树分治,每次把每个点的deep取出,排序...尺取法... # include <stdio.h> # include <stdlib.h> # include <ios ...
- 小程序 - swiper除了左右切换还有上下滚动超出屏幕的内容
本来呢,我是有专门整理小程序恶心bug的文章的,每次只要添加汇总就好, 但是呢,鉴于这个问题的恶心程度,所以我把他单独拿出来说了. ---------------------------------- ...
- AJAX跨域问题解决方法(1)——禁止浏览器进行跨域限制
思路:通过命令行修改浏览器启动参数,使得浏览器不进行跨域检查,从而允许跨域 方法:命令行参数启动浏览器后添加参数--disable-web-security 例:chrome --disable-we ...
- android 获取wifi列表,如果你忽略了这个细节,可能你的软件会崩溃
一:业务描述 最近公司有一个小需求,用户点击wifi扫描按钮(注意:是用户主动点击wifi扫描按钮),app去扫描附近的wifi,显示在listView中,仅此而已,app都不用去连接某个wifi,看 ...
- MySQL的bigint类型
bigint支持的数字的大小范围为:19位,存电话号码.有符号范围:-9223372036854775808 到 9223372036854775807 int支持的数字范围为:10位,有符号范围:- ...
- Django基础(二):环境配置
前戏 WEB框架简介 具体介绍Django之前,必须先介绍WEB框架等概念. web框架: 别人已经设定好的一个web网站模板,你学习它的规则,然后“填空”或“修改”成你自己需要的样子. 一般web框 ...
- 为什么会有可恶的腾讯电脑管家&怎么干掉它-电脑开机出现腾讯电脑管家-无法卸载腾讯电脑管家
为什么会有可恶的腾讯电脑管家 怎么干掉它 电脑开机出现腾讯电脑管家 无法卸载腾讯电脑管家 某天,趁空闲,升级了一些常用软件,其中就升了新版电脑qq,晚上玩完电脑后关机睡觉,第二天早上开机.出现了图一: ...