Activity的启动过程

简介:

今天我们来分析下Activity的启动流程,看看Activity是啥时候创建的,窗口是啥时候创建的,Context呢?

我们启动一个Activity时一般是这样的:

Intent intent = new Intent(MainActivity.this, TestActivity.class);
startActivity(intent);

实际上startActivity调用的是Activity类里面的方法,在Activity类中startActivity有多个重载方法,但最后调用的都是startActivityForResult方法

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    //mParent代表的是ActivityGroup,肯定是null的
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

看上面的源码,这里需要注意的是这里会走mParent==null这个分支。mParent代表的是ActivityGroup,也就是一个Activity里面再嵌套Activity,这种方式已经被Fragment替代了。

这里的mMainThread就是ActivityThread,而mMainThread.getApplicationThread()就是ActivityThread的内部类ApplicationThread。ActivityThread和ApplicationThread在Activity的启动过程中发挥了很重要的作用。

//Instrumentation.class
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    //这里可以看到ApplicationThread其实是个Binder
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    ...
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        //调用ActivityManagerNative的getDefault方法返回ActivityManagerService
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //这个方法用于检查Activity的启动结果,如果启动失败是抛出相应的异常
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

从Instrumentation的execStartActivity源码可以看到,ApplicationThread其实是个Binder,它主要是供后面从ActivityManagerService的进程回调到应用的进程。同时启动Activity的过程通过Binder机制转到了ActivityManagerService。

ActivityManagerService中的Activity的启动过程就相对复杂很多,需要经过很多的跳转和处理,比如需要判断要启动的Activity的任务栈是否存在,不存在的话要创建任务栈;暂停当前的Activity,以便当前待启动的Activity可以获取焦点等。这里我们就不跟进去看源码了,容易绕晕。

ActivityManagerService做好自己的事儿以后,就会调用我们传过去的Binder对象ApplicationThread的scheduleLaunchActivity来将进程切换到当前应用的进程,以便继续完成启动Activity的任务。

//ApplicationThread.class
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ...) {

    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();

    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    r.voiceInteractor = voiceInteractor;
    r.activityInfo = info;
    ...
    
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

ActivityClientRecord中保存了要启动的Activity的信息。由于ApplicationThread是一个Binder,所以scheduleLaunchActivity是运行在Binder线程池中的,需要通过Handler将线程切换到ActivityThread的线程中去。而上面源码中的H就是ActivityThread中的Handler。

private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
    public static final int PAUSE_ACTIVITY          = 101;
    public static final int STOP_ACTIVITY_SHOW      = 103;
    public static final int STOP_ACTIVITY_HIDE      = 104;
    public static final int RECEIVER                = 113;
    public static final int CREATE_SERVICE          = 114;
    public static final int SERVICE_ARGS            = 115;
    public static final int STOP_SERVICE            = 116;
    ...
    
    String codeToString(int code) {
        if (DEBUG_MESSAGES) {
            switch (code) {
                case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
                case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
                case RECEIVER: return "RECEIVER";
                case CREATE_SERVICE: return "CREATE_SERVICE";
                case SERVICE_ARGS: return "SERVICE_ARGS";
                case STOP_SERVICE: return "STOP_SERVICE";
                ...
            }
        }
        return Integer.toString(code);
    }
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
            ...
    }

可以看到这个Handler里面大量的跟四大组件有关的方法,其他的组件的一些启动停止等都会回调到这里,由这个Handler处理。

我们看到Handler H对LAUNCH_ACTIVITY的处理是通过ActivityThread的handleLaunchActivity方法

//ActivityThread.class
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

        if (!r.activity.mFinished && r.startsNotResumed) {
            
            performPauseActivityIfNeeded(r, reason);

            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        try {
            ActivityManagerNative.getDefault()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

从源码中我们可以看到启动Activity的过程最后由performLaunchActivity来完成,完成以后就会调用handleResumeActivity方法来调用启动的Activity的onResume方法。

performLaunchActivity主要完成了以下几件事:

(1)从ActivityClientRecord中获取待启动的Activity组件的信息

ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
    r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
            Context.CONTEXT_INCLUDE_CODE);
}

ComponentName component = r.intent.getComponent();
if (component == null) {
    component = r.intent.resolveActivity(
        mInitialApplication.getPackageManager());
    r.intent.setComponent(component);
}

if (r.activityInfo.targetActivity != null) {
    component = new ComponentName(r.activityInfo.packageName,
            r.activityInfo.targetActivity);
}

(2)通过Instrumentation类的newActivity方法,利用类加载器来创建Activity

Activity activity = null;
try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
} catch (Exception e) {
    if (!mInstrumentation.onException(activity, e)) {
        throw new RuntimeException(
            "Unable to instantiate activity " + component
            + ": " + e.toString(), e);
    }
}

newActivity方法直接用类加载器加载类

//newActivity方法直接用类加载器加载类
public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}

(3)调用LoadApk的makeApplication创建Application对象,如果Application对象已经存在则不会重新创建

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    //如果已经存在mApplication,则不创建,所以一个应用只有一个Application
    if (mApplication != null) {
        return mApplication;
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            //调用Application的OnCreate方法
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }
    ...
    
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    return app;
}

(4)创建ContextImpl对象并通过Activity的attach方法完成关联和其他初始化操作

//调用createBaseContextForActivity方法创建ContextImpl
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
    config.updateFrom(r.overrideConfig);
}

Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
    window = r.mPendingRemoveWindow;
    r.mPendingRemoveWindow = null;
    r.mPendingRemoveWindowManager = null;
}
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);

Activity的attach方法会完成绑定ContextImpl,创建Window,关联Application等任务

//Activity.class
final void attach(Context context, ActivityThread aThread,
        ...
        Window window) {
    //绑定ContextImpl 
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);

    //创建Window并设置回调监听
    mWindow = new PhoneWindow(this, window);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
        mWindow.setSoftInputMode(info.softInputMode);
    }
    if (info.uiOptions != 0) {
        mWindow.setUiOptions(info.uiOptions);
    }
    mUiThread = Thread.currentThread();

    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    
    ...
}

(5)调用Activity的onCreate方法

activity.mCalled = false;
if (r.isPersistable()) {
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
    mInstrumentation.callActivityOnCreate(activity, r.state);
}

这样Activity就启动完毕了。

总结

通过对在应用里面启动新的Activity的过程进行源码跟踪,我们发现这里面主要涉及到几个类:Activity、ActivityThread、ApplicationThread、ActivityManagerService。

(1)Activity是我们发起启动新的Activity的入口,也是最后完成Activity操作结束的地方。我们通过Activity的startActivity发起启动新Activity的请求,最后通过Activity的attach方法完成Context的绑定和窗口Window的创建和绑定。

(2)ActivityThread是启动Activity的处理者,也是一个中间人的角色,通过调用其他几个类完成启动Activity的任务。它首先通过Binder机制调用ActivityManagerService完成Activity相关的系统级的操作,比如任务栈,暂停其他Activity等,然后通过内部的Binder类ApplicationThread接收ActivityManagerService的进程间请求,将启动的操作重新转回到当前应用进程。接着通过调用Instrumentation和LoadApk的相关方法完成加载Activity类和Application的任务。最后调用Activity的attach方法完成一系列的绑定操作。

(3)ApplicationThread是一个Binder类,用于和ActivityManagerService的进程间通信。

(4)ActivityManagerService是系统的一个服务,用于管理Activity的状态和相关信息,比如任务栈等。

如果是直接点击桌面的应用图标启动应用呢?其实这个过程和启动Activity类似,都是需要启动一个Activity。不过启动应用启动的是应用的入口Activity,同时是从桌面应用启动另一个应用程序的Activity,所以过程肯定会多一些步骤,比如要找到应用中的入口Activity,创建新的应用程序进程,要创建任务栈,要移除桌面的焦点等。等这些准备工作都好了以后,后面就相当于是启动一个Activity的过程了。有兴趣的童鞋可以研究一下。



欢迎关注我的微信公众号,和我一起每天进步一点点!
AntDream
目录
相关文章
|
7月前
fragment启动activity方法
fragment启动activity方法
60 1
|
存储 Android开发
Activity的启动模式和启动流程
标准模式(standard) 栈顶复用模式(singleTop) 栈内复用模式(singleTask) 单例模式(singleInstance) 启动模式可在AndroidManifest.xml中,通过<activity>标签的android:launchMode属性设置。
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(二)
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(二)
224 0
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(二)
|
Linux Android开发
【Android 启动过程】Android 应用启动流程 | Activity 启动流程
【Android 启动过程】Android 应用启动流程 | Activity 启动流程
422 0
【Android 启动过程】Android 应用启动流程 | Activity 启动流程
|
消息中间件 Android开发
个人学习笔记:事件分发和启动Activity
个人学习笔记:事件分发和启动Activity
128 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( Activity -> AMS、主线程阶段 )
【Android 启动过程】Activity 启动源码分析 ( Activity -> AMS、主线程阶段 )
214 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)
236 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )
494 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )
236 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 一 )(一)
【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 一 )(一)
161 0

热门文章

最新文章