美文网首页
View篇_01WindowManagerService、Win

View篇_01WindowManagerService、Win

作者: 冉桓彬 | 来源:发表于2019-04-14 10:23 被阅读0次

前言:
  Android系统中的窗口是屏幕上的一块用于绘制各种UI元素并可以响应用户输入的一个矩形区域, 从原理上来讲, 窗口的概念是独自占有一个Surface实例的显示区域, 例如Dialog、Activity的界面、壁纸、状态栏以及Toast等都是窗口;
  Surface是一块画布, 应用可以随心所欲地通过Canvas或者OpenGL在其上作画, 然后通过SurfaceFlinger将多块Surface的内容按照特定的顺序进行混合并输出到FrameBuffer, 从而将Android界面显示给用户;
  既然每个窗口都有一块Surface供自己涂鸦, 必然需要一个角色对所有窗口的Surface进行协调管理. 于是WMS应运而生, WMS为所有窗口分配Surface, 掌管Surface的显示顺序以及位置尺寸, 控制窗口动画, 并且还是输入系统的重要的中转站;

一、WindowManagerService实例的创建

  1. WindowManagerService运行在system_server进程中, system_server进程在创建时会初始化WindowManagerService的实例;
  2. 窗口管理服务, 复杂窗口的启动, 添加, 删除等;
  3. 这篇笔记希望分析一下Activity的展示与AMS到底有怎样的关系?
1.1 SystemServer.main

system_server进程被创建以后, 会调用SystemServer.main方法

public final class SystemServer {
    public static void main(String[] args) {
        new SystemServer().run();
    }
    private void run() {
        //**
         * 核心是这三个方法, AMS在第一个方法中被初始化;
         */
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    }
    private void startBootstrapServices() {
        //**
         * 通过SSM拿到AMS的实例;
         */
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
    }
}

二、Activity端


Activity启动的流程比较复杂, 目前结合Activity的生命周期只列出Activity启动时的方法调用链

ActivityMain.main--->
ActivityThread.handleLaunchActivity--->
ActivityThread.performLaunchActivity--->
ActivityThread.handleResumeActivity--->
ActivityThread.performResumeActivity--->
2.1 ActivityThread.handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    // 获取AMS的实例;
    WindowManagerGlobal.initialize();
    Activity a = performLaunchActivity(r, customIntent);
}
2.2 WindowManagerGlobal.initialize
public static void initialize() {
    getWindowManagerService();
}
public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            // 进程间通信获取WindowManagerService实例;
            sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
        }
        // WindowManagerGlobal持有sWindowManagerService的引用;
        return sWindowManagerService;
    }
}
2.3 ActivityThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 通过Activity.attach将Activity, Window, WindowManager, WMS进行绑定;
    activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
}
2.4 Activity.attach
先理一下各个变量之间的继承关系:
public class Activity {
    Window mWindow = new PhoneWindow();
    WindowManager mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(PhoneWindow);
}
public class WindowManagerImpl extends WindowManager {
    private final Window mParentWindow = new PhoneWindow();
}
public class Activity {
    final void attach(...) {
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        ...
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        ...
        mWindowManager = mWindow.getWindowManager();
    }
}

三、ActivityThread.handleResumeActivity

在handleLauncherActivity里面会执行onCreate方法, 然后触发对布局的解析, 根节点为DecorView, resume方法里面对View树进行遍历测量, 布局, 绘制;

3.1 ActivityThread.handleResumeActivity
final void handleResumeActivity(...) {
    // 其他几个地方看到了再进行分析吧, 目前先分析这个方法;
    r.activity.makeVisible();
}
3.2 Activity.makeVisible
void makeVisible() {
    if (!mWindowAdded) {
        // 由前面的关系可知, 这里的wm指向的是ViewManagerImpl;
        // ViewManagerImpl与DecorView之间有什么关系?
        ViewManager wm = getWindowManager();
        wm.addView(mDecor, getWindow().getAttributes());
        mWindowAdded = true;
    }
    mDecor.setVisibility(View.VISIBLE);
}
3.3 WindowManagerImpl.addView
// mGlobal持有WMS;
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    // 1. mParentWindow指向的是PhoneWindow;
    // 2. view指向的是DecorView;
    // 3. setContentView时, 已经将PhoneWindow与DecorView进行了关联;
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
3.4 WindowManagerGlobal.addView
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
        parentWindow.adjustLayoutParamsForSubWindow(wparams);
    }
    ViewRootImpl root;
    View panelParentView = null;
    synchronized (mLock) {
        int index = findViewLocked(view, false);
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        // WindowManagerGlobal持有两个容器: mViews用于存储DecorView, mRoots用于存储ViewRootImpl;
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
        // 这里以及后续的View都默认为DecorView, ViewRootImpl通过setView将DecorView与自己进行绑定;
        root.setView(view, wparams, panelParentView);
    }
}
3.5 ViewRootImpl.setView
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    // 现在只看这三行代码:
    // 1. 将DecorView赋值给View mView;
    // 2. 重新布局时会调用这个requestLayout, 如果在子线程中操作UI会报错, 报错原因就在这个requestLayout中;
    // 3. 将ViewRootImpl赋值给DecorView, 将两者进行相互绑定, DecorView为每一个视图的根节点, 其内部维护ViewRootImpl
    //    实例从而实现了每次View通过ViewRootImpl的渲染;
    mView = view;
    requestLayout();
    view.assignParent(this);
}

@Override
public void requestLayout() {
    // 通常所说的不能在非UI线程中操作UI就是在这里进行判断的;
    checkThread();
    mLayoutRequested = true;
    // 这个方法会触发View的测量, 绘制, 布局操作;
    scheduleTraversals();
}
void checkThread() {
    // 在初始化ViewRootImpl时会在当前线程生成一个常量mThread, 操作View时判断当前线程是否与ViewRootImpl
    // 初始化时的线程是同一个线程, 如果不是就会报错;
    if (mThread != Thread.currentThread()) {
        throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
    }
}
final Thread mThread;
public ViewRootImpl(Context context, Display display) {
    mThread = Thread.currentThread();
}

相关文章

网友评论

      本文标题:View篇_01WindowManagerService、Win

      本文链接:https://www.haomeiwen.com/subject/rhhucqtx.html