WmS简介(三)之Activity窗口是如何创建的?基于Android7.0源码

举报
江南一点雨 发表于 2021/08/17 00:11:55 2021/08/17
【摘要】 OK,在前面两篇博客中我们分别介绍了WmS中的token,同时也向小伙伴们区分了Window和窗口的区别,并且按照type值的不同将Android系统中的窗口分为了三大类,那么本篇博客我们就来看看应用窗口(即Activity所对应的窗口)到底是怎么创建出来的,如果小伙伴们尚不理解WmS中的token,或者不清楚Window和窗口的区别,可以先看看下面两篇博客,可以帮助你理解本...

OK,在前面两篇博客中我们分别介绍了WmS中的token,同时也向小伙伴们区分了Window和窗口的区别,并且按照type值的不同将Android系统中的窗口分为了三大类,那么本篇博客我们就来看看应用窗口(即Activity所对应的窗口)到底是怎么创建出来的,如果小伙伴们尚不理解WmS中的token,或者不清楚Window和窗口的区别,可以先看看下面两篇博客,可以帮助你理解本文:

1.WmS详解(一)之token到底是什么?基于Android7.0源码

2.WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码

如果小伙伴没有研究过Activity中的setContentView方法到底是做什么用的,可以先看看下面两篇文章,因为本文中有一些知识点涉及到这些东西:

1.View绘制详解,从LayoutInflater谈起

2.View绘制详解(二),从setContentView谈起

有了上面的知识基础之后,再来看本篇博客应该就没有难度了。

OK,那我们就正式开始今天的介绍。

首先小伙伴要明白,Activity所对应的窗口和Activity自身并不是同一个东西,Activity对应的窗口我们在上篇博客中称之为应用窗口,由于每一个应用窗口都对应了一个Activity对象,因此在创建应用窗口之前我们首先要创建一个Activity对象。当Ams决定要启动一个Activity的时候,首先会通知客户端进程,而每个客户端进程都会对应一个ActivityThread类,启动Activity的任务最终就是由这个ActivityThread来完成。其实说到底,启动Activity不就是创建一个Activity对象么?我们来看看创建代码,在ActivityThread方法中有一个performLaunchActivity方法,这个方法就是用来启动一个Activity的,该方法中有这样几行代码:


  
  1. Activity activity = null;
  2. try {
  3. java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
  4. activity = mInstrumentation.newActivity(
  5. cl, component.getClassName(), r.intent);
  6. StrictMode.incrementExpectedActivityCount(activity.getClass());
  7. r.intent.setExtrasClassLoader(cl);
  8. r.intent.prepareToEnterProcess();
  9. if (r.state != null) {
  10. r.state.setClassLoader(cl);
  11. }
  12. } catch (Exception e) {
  13. if (!mInstrumentation.onException(activity, e)) {
  14. throw new RuntimeException(
  15. "Unable to instantiate activity " + component
  16. + ": " + e.toString(), e);
  17. }
  18. }

OK,在完成Activity的构造之后,接下来我们就可以调用Activity的attach方法了,这个方法主要用来初始化Activity的一些基本变量:


  
  1. activity.attach(appContext, this, getInstrumentation(), r.token,
  2. r.ident, app, r.intent, r.activityInfo, title, r.parent,
  3. r.embeddedID, r.lastNonConfigurationInstances, config,
  4. 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);
 

mWindow.setCallback(this);
 


OK,Window对象创建成功之后,接下来我们需要给Window对象中的mWindowManager变量赋值,这个变量的类型就是一个WindowManager类,WindowManager是一个interface,这个接口有一个实现类WindowManagerImpl,WindowManagerImpl中是对WindowManager的真正实现。我们来看一下是如何给mWindowManager赋值的:


  
  1. mWindow.setWindowManager(
  2. (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
  3. mToken, mComponent.flattenToString(),
  4. (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
  5. if (mParent != null) {
  6. mWindow.setContainer(mParent.getWindow());
  7. }
  8. mWindowManager = mWindow.getWindowManager();

OK,再来看看setWindowManager方法内部:


  
  1. public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
  2. boolean hardwareAccelerated) {
  3. mAppToken = appToken;
  4. mAppName = appName;
  5. mHardwareAccelerated = hardwareAccelerated
  6. || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
  7. if (wm == null) {
  8. wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
  9. }
  10. mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
  11. }
  12. public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
  13. return new WindowManagerImpl(mContext, parentWindow);
  14. }

WmS详解(一)之token到底是什么?基于Android7.0源码

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谈起这篇博客。


至此,一个应用窗口就创建成功了。


参考资料:


Android Window 三 创建应用窗口



文章来源: wangsong.blog.csdn.net,作者:_江南一点雨,版权归原作者所有,如需转载,请联系作者。

原文链接:wangsong.blog.csdn.net/article/details/53239925

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。