前面讲了onCreat中详细做了什么 深化了解Activity的显现原理(1)

接下来看看onResume生命周期中做了什么

Activity.onResume

ActivityThread.java

public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
        String reason) {
    ...
    final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    ...
    if (r.window == null && !a.mFinished && willBeVisible) {
        r.window = r.activity.getWindow();
        View decor = r.window.getDecorView();
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager();
        ...
        //1.拿到Activity持有的mWindowManager后调用addView
        wm.addView(decor, l);
    }
    if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
        ...
        if (r.activity.mVisibleFromClient) {
            //2.
            r.activity.makeVisible();
        }
    }
    ...
}

    ActivityThread 会依据恳求创立办理着四大组件的生命周期办法的调用,onResume生命周期是在ActivityThread的handleResumeActivity办法中去调用的。在这个办法中先是经过performResumeActivity的方法触发了activity的回调,然后判断了activity未封闭而且要显现时,会取出activity的DecorView,把DecorView增加到ViewManager。这个ViewManager其实是Activity持有的一个WindowManager。

    最终调用activity的makeVisible办法,把activity设置为可见的。其实makeVisiblel办法所做的仅仅是把activity的DecorView设置为可见状况,这并不足以支撑完成悉数的制作工作,仅仅触发了一次重绘。所以重点仍是要分析addView详细是怎样操作的。

ViewManager.addView

源码
//Activity.java
private WindowManager mWindowManager;
final void attach() {
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    //获取WindowManager
    mWindowManager = mWindow.getWindowManager();
    ...
}
--------------------
//Windows.java
public WindowManager getWindowManager() {
    return mWindowManager;
}
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
        boolean hardwareAccelerated) {
    mAppToken = appToken;
    mAppName = appName;
    mHardwareAccelerated = hardwareAccelerated;
    if (wm == null) {
        wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
    }
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
---------------------
//WindowManagerImpl.java
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    ...
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

    每个activity在初始化的时分都会持有一个WindowManager。而且是经过每个activity自己的phonewindow的getWindowManager办法来获取的。用于办理Window上的View,包含addViewremove

    在Windows.java可以看到用来addView的WindowManager是经过createLocalWindowManager办法自己创立的一个WindowManagerImpl实例。所以接着看WindowManagerImpl类的addView办法,发现最终是调用了WindowManagerGlobal的addView办法。

//WindowManagerGlobal.java
public static WindowManagerGlobal getInstance() {
    synchronized (WindowManagerGlobal.class) {
        if (sDefaultWindowManager == null) {
            sDefaultWindowManager = new WindowManagerGlobal();
        }
        return sDefaultWindowManager;
    }
}
public void addView(View view, ViewGroup.LayoutParams params,
    Display display, Window parentWindow) {
    ...
    root = new ViewRootImpl(view.getContext(), display);
    view.setLayoutParams(wparams);
    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    ...
    root.setView(view, wparams, panelParentView);
}

    WindowManagerGlobal是个单例。在调用addView办法之后,如果是首次增加的状况,会创立一个ViewRootImpl实列root,而且把view和root缓存到单例的特点中,最终再调用setView办法。

ViewRootImpl.setView

final W mWindow;
View mView;
final IWindowSession mWindowSession;
static class W extends IWindow.Stub {}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    if (mView == null) {
        mView = view;
        ...
        requestLayout();//触发布局和制作
        ...
        res = mWindowSession.addToDisplay(mWindow, ...);//告诉WMS增加窗口
        ...
        view.assignParent(this);
    }
}

    mView为空的时分,调用requestLayout办法来触发布局和制作。

    addToDisplay这个办法的效果便是告诉WMS增加窗口。调用WMS肯定是跨进程通讯,参数中的mWindow是一个W类型的静态内部类,这个类继承了IWindow.Stub用来和WMS进行双向通讯。这儿用到的mWindowSession,同样是一个跨进程通讯的句柄,是一个Binder服务代理,是App端向WMS发送音讯的通道。

    在办法的最终,调用view的assignParent办法,这个View便是咱们上文的DecorView,把decorView的parent设置为了ViewRootImpl。这样做的意图便是让ViewRootImpl可以办理整个viewTree。

    总结一下到目前为止的流程。首先在Activity的attach过程中,除了创立了phoneWindow,还为activity创立了一个WindowManager,以便办理整个phoneWindow。在onResume生命周期中,会调用WindowManager的addView增加decorView。那么当WindowManager办理viewTree的时分,会给viewTree分配一个ViewRootImpl。ViewRootImpl的责任便是办理viewTree的制作工作,包含viewTree的显现、测量、同步刷新以及事情分发等等,和担任与其他的服务进行通讯。

WMS通讯

    在多个 Activity 一起存在的状况下,每个 Activity 都有自己独立的窗口相关对象,包含 PhoneWindow、DecorView 和 WindowManagerImpl。这样可以确保每个 Activity 的窗口操作彼此独立,互不搅扰。WindowManagerGlobal作为一个全局的单例,持有每个activity的rootView ,mWindowSession和mWindow分别是和WMS进行双向通讯的句柄。

深入理解Activity的显示原理(2)

总结

深入理解Activity的显示原理(2)
    Activity的attach办法中会初始化PhoneWindow以及WindowManager,setContentView办法中创立了DecorView,而且把咱们自己实现的布局转化成了viewTree挂载在了DecorView的contentParent下面,形成了一个完整的ViewTree。

    最终activity的onResume生命周期里,经过addView的方法创立了ViewRootImpl,而且用它来办理viewTree的制作工作。ViewRootImpl可以了解为“View树的办理者”——它有一个mView成员变量,其指向Window和Activity中共同拥有的mDecor对象,即View树的根DecorView。windowSession以及mWindow是用来和WMS进行双向通讯的。最终再经过requestLayout显现activity中的内容。

/post/684490…

mp.weixin.qq.com/s/iMQ5xF7K3…

blog.51cto.com/u_16113862/…