在我们平时写代码的时候,经常要用到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
下面看下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
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
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
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的启动,我觉得没必要增加这个,用到的时候获取一下也好