Activity启动过程分析

原文: Android中Activity启动过程探究   https://www.cnblogs.com/kross/p/4025075.html

这篇文章是对上面文章的总结  

1.因为Android也是 Java程序,所以 必然有一个Main方法入口,这个入口,就是在ActivityThread中,因此首先 调用android.app.ActivityThread.main()方法

2.在ActivityThread中有一个继承于Handler的内部类,名叫H,这个H结合Looper和MessageQuene等用于ActivityThread这个主线程的消息处理机制,在H的handleMessage()方法中,有个LAUNCH_ACTIVITY的what值,从字面意思来看就是启动Activity的意思,这个分支下又调用了android.app.ActitityThread.handleLaunchActivity(), 如下图

Activity启动过程分析

3.handleLaunchActivity()方法中又先后调用preformLaunchActivity()handleResumeActivity(),并且preformLaunchActivity()方法生成了Activity对象,在判断Activity对象不等于null的情况下,接着调用了 handleResumeActivity()

Activity启动过程分析

3.1 preformLaunchActivity()方法:其中mInstrumentation.callActivityOnCreate(activity, r.state)则是调用了Activity的onCreate方法,Activity的生命周期方法都是由Instrumentation对象来调用的。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
    ...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        //生成一个Activity对象
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        //抛出异常  Unable to instantiate activity
    }

    try {
        ...
        if (activity != null) {
            ...
            //
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config);
            ...
            //调用Activity的onCreate方法,Activity的生命周期方法都是由Instrumentation对象来调用的。
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
    }
    ...
}

3.2 android.app.activity.attach()方法 

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) {
    attachBaseContext(context);

    mFragments.attachActivity(this, mContainer, null);
    //生成一个Window对象
    mWindow = PolicyManager.makeNewWindow(this);
    //设置WindowManager
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
    mCurrentConfig = config;
}

3.3 接下来mInstrumentation.callActivityOnCreate(activity, r.state),就执行了Activity的setContentView方法了,可以参考另外一片文章:https://blog.****.net/jinchen_boke/article/details/88351987 

4.android.app.ActivityThread.handleResumeActivity()方法,这个方法在ViewRootImpl的分析中也有,如下

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
        boolean reallyResume) {
    ...
    //生成了一个ActivityClientRecord对象
    //方法内部其实是  通过Instrumentation调用Activity的onResume()方法。
    ActivityClientRecord r = performResumeActivity(token, clearHide);

    if (r != null) {
        final Activity a = r.activity;
        ...
        if (r.window == null && !a.mFinished && willBeVisible) {

            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            
            //父类引用指向子类对象,WindowManager是继承于ViewManager的
            //这个实现其实WindowManagerImpl,而WindowManagerImpl的实现里
            //又调用了WindowManagerGlocal这个类的方法,如增删改View这些方法
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (a.mVisibleFromClient) {
                a.mWindowAdded = true;

                //WindowManager添加decorView
                //这个地方底层其实就是调用了WindowManagerGlocal的addView了。
                wm.addView(decor, l);
            }
            ...
        }
    ...
    }
}

WindowManagerGlocal的addView,如下,可以看出WindowManagerGlocal的addView其实是调用了ViewRootImpl的setView

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
        ...
        ViewRootImpl root;
        View panelParentView = null;

        ...
        //获取ViewRootImpl对象
        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);

        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
     

    // do this last because it fires off messages to start doing things
    try {
        //ViewRootImpl的setView
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        ...
        throw e;
    }
}

ViewRootImpl 的setView

/**
 * We have one child
 */
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            ...
            // Schedule the first layout -before- adding to the window
            // manager, to make sure we do the relayout before receiving
            // any other events from the system.
            requestLayout(); 
            ...
            view.assignParent(this);
            ...
        }
    }
}

android.view.ViewRootImpl.requestLayout()方法 如下图

 Activity启动过程分析

android.view.ViewRootImpl.scheduleTraversals()方法,如下图

Activity启动过程分析

 在mTraversalRunnable 的 run方法中,调用了doTraversal()方法。而doTraversal()方法又调用了performTraversals()方法,这个方法非常长,依次调用了performMeasure(),performLayout(),performDraw()三个方法,进行的View的绘制。