WmS简介(三)之Activity窗口是如何创建的?基于Android7.0源码
OK,在前面两篇博客中我们分别介绍了WmS中的token,同时也向小伙伴们区分了Window和窗口的区别,并且按照type值的不同将Android系统中的窗口分为了三大类,那么本篇博客我们就来看看应用窗口(即Activity所对应的窗口)到底是怎么创建出来的,如果小伙伴们尚不理解WmS中的token,或者不清楚Window和窗口的区别,可以先看看下面两篇博客,可以帮助你理解本文:
1.WmS详解(一)之token到底是什么?基于Android7.0源码
2.WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码
如果小伙伴没有研究过Activity中的setContentView方法到底是做什么用的,可以先看看下面两篇文章,因为本文中有一些知识点涉及到这些东西:
2.View绘制详解(二),从setContentView谈起
有了上面的知识基础之后,再来看本篇博客应该就没有难度了。
OK,那我们就正式开始今天的介绍。
首先小伙伴要明白,Activity所对应的窗口和Activity自身并不是同一个东西,Activity对应的窗口我们在上篇博客中称之为应用窗口,由于每一个应用窗口都对应了一个Activity对象,因此在创建应用窗口之前我们首先要创建一个Activity对象。当Ams决定要启动一个Activity的时候,首先会通知客户端进程,而每个客户端进程都会对应一个ActivityThread类,启动Activity的任务最终就是由这个ActivityThread来完成。其实说到底,启动Activity不就是创建一个Activity对象么?我们来看看创建代码,在ActivityThread方法中有一个performLaunchActivity方法,这个方法就是用来启动一个Activity的,该方法中有这样几行代码:
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
这里通过一个反射,我们使用ClassLoader来装载即将要启动的Activity,实际上就是构造一个新的Activity变量。
OK,在完成Activity的构造之后,接下来我们就可以调用Activity的attach方法了,这个方法主要用来初始化Activity的一些基本变量:
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
这里传递的参数较多,我们来看看几个重要的参数:
appContext:我们知道Activity继承自ContextThemeWrapper,但是ContextThemeWrapper在构造的时候,需要一个Context参数,就是从这里传入,那么这里的appContext通过代码追踪我们最终发现这个appContext实际上是通过new了一个ContextImpl对象来获取的。
this:由于在Activity类中还需要调用主程序中的相关方法,因此这里要传入主程序的引用
r.token:r是一个ActivityClientRecord对象,这里传入的r的token实际上就是AmS中的token对象
r.parent:由于一个Activity可以有一个父Activity,这个是在Fragment出现之前,实现选项卡效果的常用策略,现在已经基本上不会再用到了
OK,这里是我们attach方法调用时的几个重要参数,在Activity的attach方法里边,有这样一行代码是系统为该Activity创建Window时调用的:
mWindow = new PhoneWindow(this, window);
这里才是创建Activity对应的窗口,窗口创建成功之后,接下来设置这个Window的Callback接口的值为当前Activity对象,如下:
mWindow.setCallback(this);
这也就是为什么我们的Activity能够收到用户消息,原因在这里。
OK,Window对象创建成功之后,接下来我们需要给Window对象中的mWindowManager变量赋值,这个变量的类型就是一个WindowManager类,WindowManager是一个interface,这个接口有一个实现类WindowManagerImpl,WindowManagerImpl中是对WindowManager的真正实现。我们来看一下是如何给mWindowManager赋值的:
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();
OK,再来看看setWindowManager方法内部:
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);
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
我们看到,这里实际上是根据传入的参数最终new了一个WindowManagerImpl出来。在setWindowManager的时候,第二个参数是一个mToken,这个mToken是从attach方法传进来的,实际上它就是AmS中Activity对应的ActivityRecord的Binder引用,从这里传来以后,这个mToken的值最终也将作为Window中mAppToken的值,这也是我们在WmS详解(一)之token到底是什么?基于Android7.0源码这篇博客中总结的Activity中的token和Window中的token一致的原因了。同时我们也看到,Activity中也有一个mWindowManager变量,该变量的值和Window对象中mWindowManager的值一致。
OK,至此,Activity中的Window对象就都已经创建完成了,接下来的事情就简单了,就是给往Window上添加View了。这个时候需要我们再回到performLaunchActivity这个方法,在这个方法调用完activity.attach方法之后,接下来又会调用callActivityOnCreate 这个方法,看名字就知道这里肯定来到了Activity的onCreate方法中,这里通过代码追踪我们最终也确实来到了Activity的onCreate方法中。接下来就是往Window中添加View了,我们已经知道Activity对应的Window实际上是一个PhoneWindow的实例,我们在Activity的onCreate方法中调用的setContentView实际上是PhoneWindow的setContentView方法,关于这里的细节我不再详述,小伙伴们有兴趣可以查看View绘制详解(二),从setContentView谈起这篇博客。
至此,一个应用窗口就创建成功了。
参考资料:
WmS简介(三)之Activity窗口是如何创建的?基于Android7.0源码的更多相关文章
- WmS详解(一)之token到底是什么?基于Android7.0源码
做Android有些年头了,Framework层三大核心View系统,WmS.AmS最近在研究中,这三大块,每一块都够写一个小册子来介绍,其中View系统的介绍,我之前有一个系列的博客(不过由于时间原 ...
- WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码
上篇博客(WmS详解(一)之token到底是什么?基于Android7.0源码)中我们简要介绍了token的作用,这里涉及到的概念非常多,其中出现频率最高的要数Window和窗口这一对搭档了,那么我们 ...
- WmS具体解释(二)之怎样理解Window和窗体的关系?基于Android7.0源代码
上篇博客(WmS具体解释(一)之token究竟是什么?基于Android7.0源代码)中我们简要介绍了token的作用,这里涉及到的概念非常多,当中出现频率最高的要数Window和窗体这一对搭档了,那 ...
- AFNetworking 3.0 源码解读(三)之 AFURLRequestSerialization
这篇就讲到了跟请求相关的类了 关于AFNetworking 3.0 源码解读 的文章篇幅都会很长,因为不仅仅要把代码进行详细的的解释,还会大概讲解和代码相关的知识点. 上半篇: URI编码的知识 关于 ...
- Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三)
Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三) 本文是SolrCloud的Recovery策略系列的第三篇文章,前面两篇主要介绍了Recovery的总体流程,以及P ...
- Hadoop2.0源码包简介
Hadoop2.0源码包简介 1.解压源码包: 2.目录结构: hadoop-common-project:Hadoop基础库所在目录,如RPC.Metrics.Counter等.包含了其它所有模块可 ...
- Volley源码解析(三) 有缓存机制的情况走缓存请求的源码分析
Volley源码解析(三) 有缓存机制的情况走缓存请求的源码分析 Volley之所以高效好用,一个在于请求重试策略,一个就在于请求结果缓存. 通过上一篇文章http://www.cnblogs.com ...
- 【转】Android应用程序窗口(Activity)窗口对象(Window)创建指南
在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...
- Activity的绘制流程简单分析(基于android 4.0源码进行分析)
要明白这个流程,我们还得从第一部开始,大家都知道 在activity里面 setcontentview 调用结束以后 就可以看到程序加载好我们的布局文件了,从而让我们在手机上看到这个画面. 那么我们来 ...
随机推荐
- JS随机数不重复
方法一 思路:首先创建一个1到3000的数组,每次取一个数,然后去除数组中取出的这个数, 这样就可以实现永不重复. var count=3000; var originalArray=new Arra ...
- ubuntu14.4 分辨率偏低
最近出了 14.04 LTS,就想安装上玩一玩.还是用 easybcd 从 windows硬盘安装.装完之后,显示效果不好于是做了如下处理: 1. 按下windows键,搜索 "附加驱动&q ...
- [HAOI 2009]逆序对数列
Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆 ...
- [Luogu 3389]【模板】高斯消元法
Description 给定一个线性方程组,对其求解 Input 第一行,一个正整数 n 第二至 n+1 行,每行 n+1 个整数,为a1,a2⋯an和 b,代表一组方程.1,a2⋯an ...
- [SDOI2011]黑白棋
Description 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 ...
- [JLOI2015]管道连接
题目描述 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的通道连接困扰.该部门有 n 个情报站,用 1 到 n 的整数编号.给出 m 对情报站 ui;vi 和费用 wi,表示情报站 ui 和 v ...
- [LSGDOJ 1505]售货员的难题 状压DP
题目描述 某 乡有n个村庄(1<n<15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村 到B村与B村到A村的路大多不同.为了提高 ...
- 例 7-10 uva12212(迭代加深搜索)
题意:对于一段数字,每次可以剪切一段连续的自然数,粘贴到任意部分,使其变成升序 思路: 考虑的是进行搜索,深搜并不能保证是最短,广搜感觉每层的情况太多. 迭代加深:枚举搜索深度,然后进行深搜. 这种方 ...
- poj3580 splay树 REVOVLE循环
SuperMemo Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12795 Accepted: 3989 Case T ...
- [bzoj4813][Cqoi2017]小Q的棋盘
来自FallDream的博客,未经允许,请勿转载,谢谢. 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能在有连线的格点之间移动.整个棋盘上共有V ...