Activity中获取windowmanager的方法

         在我们平时写代码的时候,经常要用到windowmanager这个类,一般是通过addview的方式,把一个view添加到一个窗口中,在系统中,比如toast,悬浮框状态栏,通知栏,锁屏界面他们都不是平常的activity中的window,因此通过windowmanager 直接addview的方式来呈现给用户

        WindowManager wm =(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);  

         我们看下windowmanager的源码,发现

             public interface WindowManager extends ViewManager 

  其实它是个接口,没有具体的实现类。必须要有实际的对象才行,因此,我们来找下实现它的类。经过对代码的搜索,找到WindowManagerImpl  这个类实现了WindowManager 。并且实现了addview的方法。

public final class WindowManagerImpl implements WindowManager


   接下来,我们看,这个对象是怎么找到的,继续是从context获取,那么熟悉android的一定知道,Context是个抽象类,继承context的组件有activity,service和application,

其中的getSystemService是个空实现,真正起作用的是contextImpl.java,

     public abstract Object getSystemService(@ServiceName @NonNull String name);

 而下面这个是传class的时候才用,Context.WINDOW_SERVICE是个String类型
    @SuppressWarnings("unchecked")
    public final T getSystemService(Class serviceClass) {

下面看下contextImpl中getSystemService的方法

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

SystemServiceRegistry.java中

    /**
     * Gets a system service from a given context.
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

其中    private static final HashMap> SYSTEM_SERVICE_FETCHERS =
            new HashMap>();

要通过这个name获取hashmap中的一个ServiceFetcher,如果不会空则去getService方法,这个赋值是在下面一个

    /**
     * Statically registers a system service with the context.
     * This method must be called during static initialization only.
     */
    private static void registerService(String serviceName, Class serviceClass,
            ServiceFetcher serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }

 这个方法中进行的赋值就在此类中,赋值的时机是:

    static {

   。。。。。。。

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

  。。。。。。。

这个是静态代码块,比此类的构造函数还要优先执行,

这里插入一句,我们在添加系统服务的时候,有两处要添加代码,一处是这里,一处是在Systemserver中,也就是系统刚启动的时候,

                ServiceManager.addService(。。。);

这里在servicemanager中注册。

一般用相同的变量注册,XXXmanager获取之后,在其中内部是有通过aidl的方式获取相应的service。

我们从上面的 代码看到windowmanager是有注册的,所以会走到fetcher.getService(ctx);

    static abstract interface ServiceFetcher {
        T getService(ContextImpl ctx);
    }

这里写的很好,很多服务,并且系统还可能添加服务,因此这里用了抽象和泛型;

我们的windowmanager是添加到

    static abstract class CachedServiceFetcher implements ServiceFetcher {
        private final int mCacheIndex;


        public CachedServiceFetcher() {
            mCacheIndex = sServiceCacheSize++;
        }


        @Override
        @SuppressWarnings("unchecked")
        public final T getService(ContextImpl ctx) {
            final Object[] cache = ctx.mServiceCache;
            synchronized (cache) {
                // Fetch or create the service.
                Object service = cache[mCacheIndex];
                if (service == null) {
                    service = createService(ctx);
                    cache[mCacheIndex] = service;
                }
                return (T)service;
            }
        }


        public abstract T createService(ContextImpl ctx);
    }

  这个fetcher里面去了,所以会去createService,也就是前面我们提到的registerService这个方法里面,会返回一个new WindowManagerImpl(ctx);这个对象,并且这个service只有在空的时候,才会重新创建,因此,我们getsystemservice的时候,一个进程里面,只有一个windowmanager,addview也是WindowManagerImpl实现的具体方法。


     接下来,我要说下以后我们在Activity中获取windowmanager的时候,还是否需要去在onCreate里面去采取这种方式呢?

    WindowManager wm =(WindowManager)getSystemService(Context.WINDOW_SERVICE);  

其实我们看下源码就知道了,在Activity.java中,有这样一个方法

    /** 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);
    }

复杂程度一目了然,当然,activity其实在启动的时候已经去做了跨进程的访问,在attach方法中

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
}

      其实也影响了activity的启动,我觉得没必要增加这个,用到的时候获取一下也好





你可能感兴趣的:(Activity中获取windowmanager的方法)