PhoneWindow对象的创建

应用程序窗口需要关联一个Window对象来具体描述,Window对象提供一组通用的窗口操作的API。而Window是一个abstact类型,所以实际创建的Window对象是PhoneWindow类型的对象。

PhoneWindow对象的创建是在Activity对象创建之后创建的,而Activity对象的创建在ActivityThread.performLaunchActivity()方法才完成创建的,那么进入该方法看看:

public final class ActivityThread {
   private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
     ......
        Activity activity = null;

            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//创建Activity对象

          ......
            if (activity != null) {
                ContextImpl appContext = new ContextImpl();//创建Context对象
                   appContext.setOuterContext(activity);//在ContextImpl类中保存当前Activity对象,以便在ContextImpl能操作Activity组件。
                ......
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstance,
                        r.lastNonConfigurationChildInstances, config);


......
        return activity;
    }
}

在这个函数中,我们只能看到创建了Activity对象,ContextImpl对象。但是在这个函数中调用了 activity.attach函数,进入Activity类中看看attach函数:

 public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
     ......

    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,
            Object lastNonConfigurationInstance,
            HashMap<String,Object> lastNonConfigurationChildInstances,
            Configuration config) {

        attachBaseContext(context);//设置Activity父类中的Context对象的mBase成员变量

        mWindow = PolicyManager.makeNewWindow(this);//创建出Window对象
        mWindow.setCallback(this);//设置窗口回调接口
         if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);//设置软键盘输入区域的显示模式
          }

        ......
        mWindow.setWindowManager(null, mToken, mComponent.flattenToString());//设置本地窗口管理
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }
     ......
 }

从Activity.attach()方法的17行调用了PolicyManager.makeNewWindow(this)创建Window对象并作为返回值保存在Activity类中mWindow的成员变量中,进入该方法看看如何创建的:

public final class PolicyManager {
     private static final IPolicy sPolicy;
     static {
        ......
             Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
             sPolicy = (IPolicy)policyClass.newInstance();
        ......
    }
    public static Window  makeNewWindow(Context context) {
       return sPolicy.makeNewWindow(context);
     }
}

在第6行,它在第一次被使用的时候,就会创建一个Policy类实例,并且保存在静态成员变量sPolicy中,PolicyManager.makeNewWindow()函数其实就是调用sPolicy.makeNewWindow函数来创建出一个具体的PhoneWindow类,那么就进入Policy类的makeNewWindow去看看:

public class Policy implements IPolicy {  
    ......  

    public PhoneWindow makeNewWindow(Context context) {  
        return new PhoneWindow(context);  
    }  

    ......  
}  

从这里,终于知道为什么是创建Window对象其实是创建PhoneWindow对象了,简单粗暴的new出个PhoneWindow对象。

总结一下PhoneWindow对象创建的流程,ActivityThread.performLaunchActivity()—-> activity.attach()—>PolicyManager.makeNewWindow()—>sPolicy.makeNewWindow(context)—>new PhoneWindow(context);

通过这样的流程,PhoneWindow对象就创建出来的,然而在activity.attach()方法中,调用了mWindow =PolicyManager.makeNewWindow();把创建的PhoneWindow对象保存在Activity类中mWindow成员变量中。因此说每一个Activity组件都会关联一个具体的Window对象来描述一个具体的应用程序窗口,而这个对象真正的类型就是PhoneWindow类。

我们继续回到activity.attach()方法中,在创建完PhoneWindow对象后还做几个重要的操作,我们再进入去看看:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
     ......

    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,
            Object lastNonConfigurationInstance,
            HashMap<String,Object> lastNonConfigurationChildInstances,
            Configuration config) {

        attachBaseContext(context);//设置Activity父类中的Context对象的mBase成员变量

        mWindow = PolicyManager.makeNewWindow(this);//创建出Window对象
        mWindow.setCallback(this);//设置窗口回调接口
         if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);//设置软键盘输入区域的显示模式
          }

        ......
        mWindow.setWindowManager(null, mToken, mComponent.flattenToString());//设置本地窗口管理
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();//保存在Window类的mWindowManager成员变量中
        mCurrentConfig = config;
    }
     ......
 }

在18行中设置窗口回调接口, 在20行设置软键盘输入区域的显示模式,在24行设置本地窗口管理。在28行中,把WindowManager对象保存在Window类的mWindowManager成员变量中。

我们先去看看设置窗口回调,调用了 mWindow.setCallback(this);mWindow成员变量是Window类 ,实际指向的是PhoneWindow类。

public abstract class Window {
    ......
    private Callback mCallback;
    ......
    public void setCallback(Callback callback) {
        mCallback = callback;
    }
    ......
}

从这里可以看出,Activity组件实现了一个Callback接口,然后设置到与它所关联的一个PhoneWindow对象的父类Window的成员变量mCallback中去,这样当这个PhoneWindow对象接收到系统给它分发的IO(触摸,按键)输入事件消息,转发给与它所关联的Activity组件处理。

接下来看看设置窗口的软键盘输入区域的显示模式:

public abstract class Window {
    ......
    private boolean mHasSoftInputMode = false;
    ......
    public void setSoftInputMode(int mode) {
        final WindowManager.LayoutParams attrs = getAttributes();
        if (mode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            attrs.softInputMode = mode;
            mHasSoftInputMode = true;
        } else {
            mHasSoftInputMode = false;
        }
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

    ......
}

设置完软键盘输入区域的显示模式,在14行回调函数onWindowAttributesChanged来通知Window类所关联的Activity组件,窗口布局属性发生了变化。

接下来再看看设置本地窗口管理, mWindow.setWindowManager();,进入Window类的setWindowManger函数:

public abstract class Window {
......
  public void setWindowManager(WindowManager wm,
            IBinder appToken, String appName) {
        mAppToken = appToken;
        mAppName = appName;
        if (wm == null) {
            wm = WindowManagerImpl.getDefault();
        }
        mWindowManager = new LocalWindowManager(wm);
    }
 ......
}

在第8行调用了 wm = WindowManagerImpl.getDefault();去看看该函数:

public class WindowManagerImpl implements WindowManager {

    private static WindowManagerImpl mWindowManager = new WindowManagerImpl()
    ......
     public static WindowManagerImpl getDefault(){
        return mWindowManager;
    }
    ......
}

从这里可以看出返回了WindowManagerImpl对象。
然后Window.setWindowManager()函数第10行传入了 WindowManagerImpl对象 new出了LocalWindowManager对象保存在Window类的mWindowManager成员变量中。

总结:Window类 mWindowManager 成员变量—-> 指向的是LocalWindowManager 对象 —->LocalWindowManager 类中成员变量 —–>指向的是 WindowManagerImpl对象 。最终应用程序窗口的管理是的对象是: WindowManagerImpl对象。

那么,我们好像还不知道PhoneWindow类,Window类,Activity类,Window类,WindowManagerImpl类,LocalWindowMangaer类之间的关系?

这里写图片描述

由继承图可知,它们之间存在着,各种的组合,聚合关系。

聚合:指的是整体与部分的关系。
组合:也表示类之间整体和部分的关系。

聚合和组合的区别在于:聚合关系是“has-a”关系,组合关系是“contains-a”关系。

例如:国破家亡”,国灭了,家自然也没有了,“国”和“家”显然也是组合关系。而相反的,计算机和它的外设之间就是聚合关系,因为它们之间的关系相对松散,计算机没了,外设还可以独立存在,还可以接在别的计算机上。
利用聚合,组合主要的作用就是减少耦合。


到这里PhoneWindow对象就是这样创建出来了,再梳理整个流程:
首先在ActivityThread.performLaunchActivity() —>调用了activity.attach()方法。

然后调用PolicyManager.makeNewWindow()—>sPolicy.makeNewWindow(context)—>new PhoneWindow(context);创建出PhoneWindow对象。

创建完PhoneWindow对象还有做了一些操作,函数还会调用它的成员函数setCallback、setSoftInputMode和setWindowManager来设置窗口回调接口、软键盘输入区域的显示模式和本地窗口管理器。

创建WindowManager对象流程:
setWindowManager —>WindowManagerImpl.getDefault()—> new LocalWindowManager(wm);

END

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值