Window, WindowManager, WindowMan

2017-11-08  本文已影响0人  十二书

Window, WindowManager, WindowManagerService 的简单梳理(二)- Window 的添加过程

Window, WindowManager, WindowManagerService 的简单梳理(三)- Activiy 的 Window 的创建过程

看完任玉刚的《Android 开发艺术探索》中关于Window 和 WindowManager 的章节,想大致上把 Window, WindowManager, WindowManagerService 的关系梳理一下。
这本书上讲的算是比较明白了,如果能够硬着头皮、逐字逐句、结合源码看下来,应该是可以看明白的。
不过看完以后,总少了一点通透的感觉,可能是因为这本书里对 WindowManagerService 本身的功能讲的不多。并且,几个概念绕来绕去,很容易互相混淆。

基本概念

WindowManagerService 是非常重要的一个系统服务,在SystemServer 中启动和注册,功能也复杂的多;WindowManager 则相对简单了很多。也可以看出,我们 通过getSystemService 得到的是 WindowManager,并不是 WindowManagerService。
WindowManagerService 实现的是 IWindowManager,一个 aidl 接口。WindowManager 本身就是一个接口,继承自 ViewManager。IWindowManager 接口本身也是巨复杂,跟 WindowManager 没有一毛钱关系。

在 Activity 中获取 WindowManager

我看的代码是 API 25。Activity 中提供了2种方法获取 WindowManager。

// Activity

    /** Retrieve the window manager for showing custom windows. */
    public WindowManager getWindowManager() {
        return mWindowManager;
    }

    @Override
    public Object getSystemService(@ServiceName @NonNull String name) {
        if (getBaseContext() == null) {
            throw new IllegalStateException(
                    "System services not available to Activities before onCreate()");
        }

        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);
    }

    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,
            Window window) {
        ...
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(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 的 WindowManager 是来自 mWindow。我们都知道,Activity 的 mWindow 其实就是 PhoneWindow;并且上面的代码中有 mWindow.setWindowManager() 的调用,那就看看 setWindowManager 是怎么实现的吧。

// android.view.Window
    /**
     * Set the window manager for use by this Window to, for example,
     * display panels.  This is <em>not</em> used for displaying the
     * Window itself -- that must be done by the client.
     *
     * @param wm The window manager for adding new windows.
     */
    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);
    }

可见,setWindowManager 中,Window 并没有直接把入参的 WindowManager wm 作为自己的 mWindowManager ,而是重新创建了一个 WindowManagerImpl 对象。

那么如果直接用 mContext.getSystemService(Context.WINDOW_SERVICE),得到的又是什么呢?
从上面代码中的类型强转,已经可以看出来,是 WindowManager,不是 WindowManagerService。不过,我们还是看看代码吧。

// ContextImpl
    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

// SystemServiceRegistry
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }

    static {
        ...
        registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});
        ...
    }

总之,我们能够从 Activity 或者 Context 拿到的,就是 WindowManager 的具体实现 WindowManagerImpl,不是 WindowManagerService。

因为这几个方法的名字,让我对 WindowManager 和 WindowManagerService 的关系纠结了很久。但是,他们俩真的就没有什么关系,只是名字很像而已。

以上内容参考了《Android 开发艺术探索》,也参考了《深入理解 Android 内核设计思想》,也参考了 Android 源码,如果有理解不对的地方,那一定是我学艺不精,与两位作者无关。

上一篇 下一篇

猜你喜欢

热点阅读