Android的窗体是一个显示区域,它本身是一个抽象类,在Activity组件创建的窗体是PhoneWindow类型。本文主要介绍一下窗体的创建、窗体管理器设置。在Activity的attach方法创建窗体,初始化App进程的窗体管理器。
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) {
//创造窗体对象
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
...
//创建Window内部的窗体管理者WindowManager
mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
//WindowManager同时赋值给Activity对象
mWindowManager = mWindow.getWindowManager();
}
WindowManager提供窗体对视图的操作,实现类是WindowManagerImpl。
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
...
mWindowManager =((WindowManagerImpl)wm).createLocalWindowManager(this);
}
从上面源码看出,我们通过Context的getSystemService方法,获取窗体管理器,这个管理器是App进程窗体公用的,它不管理任何窗体,仅获取到关联屏幕。在窗体绑定管理器时,创建本地窗体管理者,将管理的窗体为参数传递给它。
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
//mDisplay是公用wm
return new WindowManagerImpl(mDisplay, parentWindow);
}
每个窗体创建一个本地窗体管理者,从上下文获取的窗体服务是公用管理器。
窗体管理服务注册与查找
SystemServiceRegistry类,static代码块调用多次registerService方法注册服务,下面是注册窗体管理器服务。
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx.getDisplay());
}
});
看一下注册方法,SystemServiceRegistry内部的HashMap。
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);
}
将服务类和字符串,字符串和ServiceFetcher保存到HashMap。
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
CachedServiceFetcher继承ServiceFetcher类,当我们通过Context的getSystemService方法查找服务时,调用的是SystemServiceRegistry类的getSystemService静态方法。
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
该方法将根据字符串,在HashMap中查找ServiceFetcher。然后,调用它的getService方法。
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
Object service = cache[mCacheIndex];
if (service == null) {
service = createService(ctx);
cache[mCacheIndex] = service;
}
return (T)service;
}
}
在ContxetImpl缓存数组查找具体服务对象,服务注册时,mCacheIndex表示注册顺序索引,是一个定值。
如果未找到,在注册时,已经针对窗体管理服务重写了createService方法,因此,返回的WindowManagerImpl对象。插入mServiceCache数组,索引是mCacheIndex,数组大小和索引是static代码段创建CachedServiceFetcher的总数和创建顺序。
服务对象仅创建一个,在ContextImpl类服务数组中缓存。其他服务也是通过ServiceFetcher的方式构建。
服务委托者
在整个App进程中,WindowManagerGlobal是单例,它提供WindowSession、Wms代理,和system_server进程Wms服务通信。Wms代理也是单例,IWindowManager业务接口。WindowSession代理,IWindowSession业务接口,Session实现类在system_server进程。
App进程远程调用,通过Wms的openSession方法建立IWindowSession远程通信通道。
@Override
public IWindowSession openSession(IWindowSessionCallback callback,
IInputMethodClient client,IInputContext inputContext) {
Session session = new Session(this, callback, client, inputContext);
return session;
}
ViewRootImpl类利用IWindowSession与Wms通信,具体暂时不详细说了。
总结
看一下窗体管理器的关系图。 窗体管理器关系图.jpgViewManager接口包括三个方法,addView,updateView和removeView操作视图,WindowManager继承它。
App进程窗体管理接口和实现类是ViewManager和WindowManagerImpl类。
每一个窗体有一个本地WindowManagerImpl对象管理器。
App进程的公用窗体管理者由SystemServiceRegistry类注册。
ContxetImpl提供服务缓存数组。
服务注册,重写createService方法,创建每一个特定的服务实例。
WindowManagerGlobal单例,所有本地窗体管理器都委托它和system_server进程的Wms服务通信。
任重而道远
网友评论