Android 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 View的重绘过程之WindowManager的addView方法的更多相关文章
- [Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法
博客首页:http://www.cnblogs.com/kezhuang/p/关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下<[Andr ...
- Android View的重绘过程之Draw
博客首页:http://www.cnblogs.com/kezhuang/p/ View绘制的三部曲,测量,布局,绘画现在我们分析绘画部分测量和布局 在前两篇文章中已经分析过了.不了解的可以去我的博客 ...
- Android View的重绘过程之Measure
博客首页:http://www.cnblogs.com/kezhuang/p/ View绘制的三部曲, 测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,Vie ...
- Android View的重绘过程之Layout
博客首页:http://www.cnblogs.com/kezhuang/p/ View绘制的三部曲,测量,布局,绘画现在我们分析布局部分测量部分在上篇文章中已经分析过了.不了解的可以去我的博客里找一 ...
- [Android FrameWork 6.0源码学习] View的重绘过程之Draw
View绘制的三部曲,测量,布局,绘画现在我们分析绘画部分测量和布局 在前两篇文章中已经分析过了.不了解的可以去我的博客里找一下 下面进入正题,开始分析调用以及函数原理 private void pe ...
- [Android FrameWork 6.0源码学习] View的重绘过程之Layout
View绘制的三部曲,测量,布局,绘画现在我们分析布局部分测量部分在上篇文章中已经分析过了.不了解的可以去我的博客里找一下 View的布局和测量一样,都是从ViewRootImpl中发起,ViewRo ...
- Android View的重绘ViewRootImpl的setView方法
博客首页:http://www.cnblogs.com/kezhuang/p/ 本篇文章来分析一下WindowManager的后续工作,也就是ViewRootImpl的setView函数的工作 /i* ...
- [Android FrameWork 6.0源码学习] View的重绘过程
View绘制的三部曲, 测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...
- Android学习Scroller(五)——具体解释Scroller调用过程以及View的重绘
PS: 该篇博客已经deprecated,不再维护.详情请參见 站在源代码的肩膀上全解Scroller工作机制 http://blog.csdn.net/lfdfhl/article/detail ...
随机推荐
- java游戏开发杂谈 - 创建一个窗体
package game1; import javax.swing.JFrame; /** * java游戏开发杂谈 * ---demo1:创建一个窗体 * * @author 台哥 * @date ...
- 《k8s-1.13版本源码分析》- Scheduler启动前逻辑
本文原始地址(gitbook格式):https://farmer-hutao.github.io/k8s-source-code-analysis/core/scheduler/before-sche ...
- 正则表达式在Java中的使用
目录 介绍 从简单例子认识正则表达式匹配 Java中对正则表达式的支持(各种语言有相应的实现) 初步认识 . + * ? 范围 认识\s \w \d - 下面介绍数字和字母的正则表达, 这是编程中使用 ...
- 纯css折叠区域-基于checkbox
Accordion Accordion即可折叠区域,和<details>标签类似,不过更灵活些.折叠区域往常多用JavaScript实现,这里就纯粹用CSS,就想法上也是异途同归. 折叠区 ...
- Snapde一个全新的CSV超大文件编辑软件
今天介绍如果数据量超过104万行Excel无法打开了,用什么软件可以打开呢?Snapde,一个专门为编辑超大型数据量CSV文件而设计的单机版电子表格软件:它在C++语言开发的Snapman多人协作电子 ...
- Centos 配置开机启动脚本启动 docker 容器
Centos 配置开机启动脚本启动 docker 容器 Intro 我们的 Centos 服务器上部署了好多个 docker 容器,因故重启的时候就会导致还得手动去手动重启这些 docker 容器,为 ...
- 不一样的 SQL Server 日期格式化
不一样的 SQL Server 日期格式化 Intro 最近统计一些数据,需要按天/按小时/按分钟来统计,涉及到一些日期的格式化,网上看了一些文章大部分都是使用 CONVERT 来转换的,SQL Se ...
- 一道编程题: 在1~n之间选择若干个数,使其和为m
这是一道很明显的动态规划的题目. 递推公式为 用sum(n, m)表示所有可能的1~n之间存在的和为m的组合 那么 sum(n,m) = sum(n-1, m) | sum(n-1, m-n) 直接上 ...
- .NET Core 给使用.NET的公司所带来的机遇
今晚在余晟的微信公众号看到了一篇文章< 从.NET/C#开发的“后继无人”说起: https://mp.weixin.qq.com/s/rO2d0xZ58Z2syqT7AaNT3w>. 这 ...
- 网站被k到可以使用关键词搜索到首页优化总结
从今年二月份,刚过完年回到公司,大约一周多过后,网站就被不知名黑客攻击,然后又因为网站标题关键词堆砌导致网站被降权,从此首页不在有我的网站的踪迹,有的只是其他页面的信息,因为刚开始接触SEO,对这一块 ...