Android WindowManagerService解析(2)

来源:互联网 发布:简谱大师 mac 编辑:程序博客网 时间:2024/05/22 13:27

一、Activity背后的Window

每个Activity都对应一个Window,Activity并不是UI真实的载体,真实载体是Activity中的Window。

Activity.java

private Window mWindow;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) {    // 1、创建Window    mWindow = PolicyManager.makeNewWindow(this);    mWindow.setCallback(this);    mWindow.getLayoutInflater().setPrivateFactory(this);    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {        mWindow.setSoftInputMode(info.softInputMode);    }    if (info.uiOptions != 0) {        mWindow.setUiOptions(info.uiOptions);    }    // 2、创建WindowManager,并将其设置到Window中    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();}public Window getWindow() {    return mWindow;}

在Activity实例化之后,会调用attach方法,这个方法是Activity最早的一个回调方法,可以看到在这个里面对Window进行了创建。

PolicyManager.java

public final class PolicyManager {    private static final String POLICY_IMPL_CLASS_NAME =        "com.android.internal.policy.impl.Policy";    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);    }}public class Policy implements IPolicy {    private static final String TAG = "PhonePolicy";    public Window makeNewWindow(Context context) {        return new PhoneWindow(context);    }}

可以看到,创建的是一个PhoneWindow实例,Window是一个抽象类,PhoneWindow继承了Window类。

既然Window是UI的载体,那么我们通常在Activity中执行setContentView方法,莫非真实执行是在Window里面,没错,你猜对了,下面我们来看看。

public void setContentView(int layoutResID) {    getWindow().setContentView(layoutResID);    initActionBar();}

哈哈,看到没有,getWindow方法返回的就是前面创建的PhoneWindow对象,所以,setContentView的真正执行者其实是Window对象。

下面看看PhoneWindow的setContentView方法。

@Overridepublic void setContentView(int layoutResID) {    if (mContentParent == null) {        installDecor();    } else {        mContentParent.removeAllViews();    }    mLayoutInflater.inflate(layoutResID, mContentParent);    final Callback cb = getCallback();    if (cb != null && !isDestroyed()) {        cb.onContentChanged();    }}

这个其实创建一个DecorView,DecorView是一个ViewGroup,然后将我们的View添加到这个DecorView中。

这里写图片描述

二、Window的大管家WindowManager

在Window的身边,有一个得力的管家就是WindowManager,它帮助Window完成各项显示操作。WindowManager的实例化也在Activity的attach方法中。

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) {    // 1、创建Window    mWindow = PolicyManager.makeNewWindow(this);    mWindow.setCallback(this);    mWindow.getLayoutInflater().setPrivateFactory(this);    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {        mWindow.setSoftInputMode(info.softInputMode);    }    if (info.uiOptions != 0) {        mWindow.setUiOptions(info.uiOptions);    }    // 2、创建WindowManager,并将其设置到Window中    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();}

在第二步中,我们看到通过context.getSystemService(Context.WINDOW_SERVICE)获取到WindowManager对象,然后及其设置到Window对象中,从而实现对Window的管理。

ContextImpl.java

@Overridepublic Object getSystemService(String name) {    ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);    return fetcher == null ? null : fetcher.getService(this);}

从SYSTEM_SERVICE_MAP这个Map中来获取服务代理对象,并且在这之前会将各类服务注册进去。

private static void registerService(String serviceName, ServiceFetcher fetcher) {    if (!(fetcher instanceof StaticServiceFetcher)) {        fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;    }    SYSTEM_SERVICE_MAP.put(serviceName, fetcher);}

上面是注册方法,下面具体看看WindowService的注册过程

registerService(WINDOW_SERVICE, new ServiceFetcher() {    Display mDefaultDisplay;    public Object getService(ContextImpl ctx) {        Display display = ctx.mDisplay;        if (display == null) {            if (mDefaultDisplay == null) {                DisplayManager dm = (DisplayManager)ctx.getOuterContext().                        getSystemService(Context.DISPLAY_SERVICE);                mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);            }            display = mDefaultDisplay;        }        return new WindowManagerImpl(display);}});

可以看到,我们通过的使用getSystemService(Context.WINDOW_SERVICE)获取得到的是一个WindowManagerImpl对象,并且它并不是一个真正的WindowManagerService的远程代理对象,而是一个对DisplayManagerService远程代理对象的封装。具体可以参考文章 Android WindowManagerService解析(1)

弄清了这个WindowManager之后,我们回过头去看看Window的setWindowManager的过程。

Window.java

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并且直接使用的前面创建一个WindowManagerImpl对象,而是通过WindowManagerImpl调用createLocalWindowManager来创建的一个WindowManagerImpl对象。

WindowManagerImpl

public final class WindowManagerImpl implements WindowManager {    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {        return new WindowManagerImpl(mDisplay, parentWindow);    }}

可以看到,它就是重新创建了一个WindowManagerImpl对象。从这里我们可以知道,在Window中的WindowManager管家是一个WindowManagerImpl对象。

三、UI的显示过程

Window仅仅只是一个载体,真正的显示是由WindowManager来处理的。

下面来看看ActivityThread的handleResumeActivity方法。

ActivityThread.java

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,        boolean reallyResume) {    ActivityClientRecord r = performResumeActivity(token, clearHide);    if (r != null) {        // 1、获取Activity对象        final Activity a = r.activity;        // 2、得到Activity的Window对象        r.window = r.activity.getWindow();        // 3、拿到Window中的decorView对象        View decor = r.window.getDecorView();        decor.setVisibility(View.INVISIBLE);        // 4、拿到WindowManager对象        ViewManager wm = a.getWindowManager();        // 5、得到WindowManger的布局属性        WindowManager.LayoutParams l = r.window.getAttributes();        a.mDecor = decor;        l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;        l.softInputMode |= forwardBit;        if (a.mVisibleFromClient) {            a.mWindowAdded = true;            // 6、调用WindowManager的addView方法            wm.addView(decor, l);        }   }

看到这里是不是很熟悉,我们平时在使用WindowManager的时候也是这样使用的,这里我们就突然明白原来Activity内部就是封装了一个windowManager,真正使用的还是它的addView方法,这个我们在使用WindowManager经常使用。
这里写图片描述

原创粉丝点击