本文基于Android 9.0源码。
前言
日常应用开发过程中,大家往往会忽略一些框架层的知识,如AMS(ActivityManagerService)、WMS(WindowMangerService)等。本专题就来讲一讲WMS源码的分析,首先直接讲WMS可能会比较难以理解,所以先从与WMS关系最直接的WindowManager切入,会使大家对WMS有一个比较清晰的思路。
源码位置
文件位置 | 功能描述 |
---|---|
/frameworks/base/core/java/android/view/ViewManager.java | WindowManager接口类 |
/frameworks/base/core/java/android/view/WindowManager.java | ViewManager接口类 |
/frameworks/base/core/java/android/view/Window.java | 抽象类,具体实现类是PhoneWindow.java |
/frameworks/base/core/java/android/view/WindowManagerImpl.java | WinodwManager接口实现类 |
/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java | Window具体实现类 |
WindowManager架构
WindowManager从字面意思就可以看出来,它的作用就是管理Window的,如文章开始介绍相关类所描述,Window.java是一个抽象类,其具体实现且唯一继承的类是PhoneWindow,而WindowManger自己也是一个接口类,它自身继承接口ViewManger,WindowManager具体的实现类是WindowManagerImpl。最终,WindowManagerImpl会将业务交给WindowManagerGlobal来处理。先给出一张具体关联图,后面对应一一解读:
WindowManager
WindowManager是一个接口类,继承接口ViewManager,ViewManger顾名思义,就是管理View的,该接口中定义了三个方法,分别用来添加、移除和更新View,代码如下:
public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
Window
前面介绍WindowManger体系图的时候说到,WindowManger就是管理Window的,Window是一个抽象类,其具体的实现类是PhoneWindow。PhoneWindow具体创建的地方是什么时候呢?在PhoneWindow的构造方法前面有一段注释:
/**
* Constructor for main window of an activity.
*/
PhoneWindow就是一个Activity最基本的窗口,他负责Activity与View系统的交互,所以PhoneWindow创建是在Activity启动过程中,在Activiy的attach方法中,PhoneWindow创建,其代码如下:
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, ActivityConfigCallback activityConfigCallback) {
...
mWindow = new PhoneWindow(this, window, activityConfigCallback);
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
...
}
从代码中可以看出,Activity创建了PhoneWindow之后,通过PhoneWindow的setWindowManager方法,与WindowManager进行绑定,setWindowManager方法具体代码如下:
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);
}
通过createLocalWindowManager,最终创建了WindowManagerImpl。可以看出,创建该实例的时候,讲window自身作为参数传递进去了,这样WindowManagerImpl就持有了Window的引用,可以对Window进行操作,例如addView,这里以addView为例,具体往下分析一下流程,如下是WindowManagerImpl中addView的代码:
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
从代码中发现,addView的具体实现并不在WindowManagerImpl中,而是继续交给一个WindowManagerGlobal中addView的方法,在深入了解WindowManagerGlobal中是如何继续实现addView之前,先了解一下WindowManagerGlobal是如何在WindowManagerImpl中创建的,其具体代码如下:
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
}
WindowManagerGlobal其实就是一个单例,说明在一个进程中只会有一个WindowManagerGlobal实例。
到这里,本文已经把Window、WindowManager以及WindowManagerImpl三者之间的关系捋了一下,WindowManager的架构也初见雏形,后面会根据此架构,深入分析源码,为大家解剖WMS。
本文已独家授权公众号ApeClub使用,转载请注明出处。关注ApeClub,更多好文与您分享。