Android Activity生命周期,启动模式,启动过程详解

待兔 等级 409 0 0

前言

接触过Android开发的同学都知道Activity,Activity作为Android四大组件之一,使用频率高。简单来说Activity提供了一个显示界面,让用户进行各种操作,本文主要分为以下三个部分:Activity的生命周期,启动模式,以及Activity的工作过程。文中大部分篇幅来自《Android开发艺术探索》一书,尽管想多以流程或图片的形式说明,奈何文笔有限,Android系统整体把握还不够深入,只能借鉴参考前辈的成果,本文主要目的是帮自己梳理Activity的相关问题,疏漏之处欢迎指出。

说明:本文中的源码都是基于Android-25版本。

Activity生命周期

生命周期

首先给出Activity的完整生命周期,如下图所示:

Android Activity生命周期,启动模式,启动过程详解

Activity生命周期

图片来源Android开发者官网

看完了完整的生命周期,我们再分别简单介绍单个生命周期含义。

  • onCreate:表示Activity正在被创建,做一些初始化工作,如加载布局文件,对一些变量或者控件进行初始化
  • onStart:表示Activity正在启动,此时Activity已经可见了,但还无法和用户交互
  • onResume:表示Activity已经在前台,可以和用户交互了
  • onPause:表示Activity正在停止,此时可以进行一些轻量级的存储数据和停止动画等工作,但不能太耗时,否则会影响到新Activity的显示,Android指定如果onPause在500ms内没有执行完毕的话就会强制关闭Activity。某些极端情况下,这个时候Activity会回到当前Activity,此时onResume会被执行,很难重现这一情形
  • onStop:表示Activity即将停止,此时Activity已经不可见了,但是Activity对象还存在内存中,没有被销毁,这个阶段也主要做一些资源回收的工作,不能太耗时
  • onDestory:表示Activity即将被销毁,可以做一些回收工作和最终的资源释放,最后一个回调方法
  • onRestart:表示Activity重新启动,当前Activity从不可见重新变为可见时会调用onRestart,这种情况一般是用户的行为导致的,比如:用户按Home键切换到桌面或者打开了一个新的Activity

三个问题

onCreate,onStart和onResume之间的区别?

  • onCreate时Activity还不可见,onStart已经可见,还不在前台,onResume已经出现在前台
  • onCreate方法只在Activity创建时执行一次,而onStart方法在Activity的切换以及按Home键返回桌面再切回应用的过程中被多次调用,因此数据恢复在onStart方法中比较合适,onResume方法可以做一些开启动画和独占设备的操作

onPause,onStop和onDestroy之间的区别?

  • onPause时Activity还可见,onStop已经不可见,但Activity对象还存在内存中,onDestroy后Activity对象就不存在了
  • 内存不足时,可能不会执行onStop方法,因此程序状态保存,停止动画,存储数据等操作最好放在onPause

切换Activity时生命周期执行顺序

假设当前Activity为A,此时用户打开Activity B,那么A和B的生命周期的执行顺序为:

Android Activity生命周期,启动模式,启动过程详解

Activity跳转生命周期.png

为了验证生命周期执行顺序,我们写个例子实测,MainActivity中单击按钮跳转到SecondActivity,然后在相应的生命周期中输出日志,如下:

public class MainActivity extends Activity {

    private static final String TAG = "MainActivity";

    ... 

    @Override
    protected void onPause(){
        super.onPause();
        Log.d(TAG,"onPause");
    }

    @Override
    protected void onStop(){
        super.onStop();
        Log.d(TAG,"onStop");
    }
}

public class SecondActivity extends Activity {

    private static final String TAG = "SecondActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"onCreate");
    }

    @Override
    protected void onStart(){
        super.onStart();
        Log.d(TAG,"onStart");
    }

    @Override
    protected void onResume(){
        super.onResume();
        Log.d(TAG,"onResume");
    }
} 

日志结果如下:

08-31 12:36:36.086 3825-3825/com.sht.user.activityjumptest D/MainActivity: onPause
08-31 12:36:36.093 3825-3825/com.sht.user.activityjumptest D/SecondActivity: onCreate
08-31 12:36:36.093 3825-3825/com.sht.user.activityjumptest D/SecondActivity: onStart
08-31 12:36:36.094 3825-3825/com.sht.user.activityjumptest D/SecondActivity: onResume
08-31 12:36:36.517 3825-3825/com.sht.user.activityjumptest D/MainActivity: onStop 

那么为什么会有这样的生命周期执行顺序呢?Android官方文档对onPause的解释为:不能在onPause中做重量级的操作,因为必须onPause执行完成以后新Activity才能Resume,同时我在分析Activity启动源过程中码也得到了相同结论。

Activity保存状态

当 Activity 暂停或停止时,Activity 的状态会得到保留。因为当 Activity 暂停或停止时,Activity 对象仍保留在内存中 ,有关其成员和当前状态的所有信息仍处于活动状态。
但是当系统的配置发生变化(屏幕旋转,语言变换等)时,Activity 被销毁,系统回调 onSaveInstanceState() 方法对有关 Activity 状态的信息进行保存,系统会向该方法传递一个 Bundle,可以在其中使用 putString()putInt() 等方法以名称-值对形式保存有关 Activity 状态的信息。当 Activity 重建时将 Bundle 同时传递给 onCreate()onRestoreInstanceState() 方法,使用上述任一方法从 Bundle 提取保存的数据并恢复该 Activity 状态。

Android Activity生命周期,启动模式,启动过程详解

Activity保存状态

图片来源Android开发者官网

onSaveInstanceState()onRestoreInstanceState() 方法中,系统自动为我们做了一定的恢复工作,布局中的每个 View 调用自己的 onSaveInstanceState() 方法,让每个视图都能保存自身需保存的信息。
每个 View 都有 onSaveInstanceState()onRestoreInstanceState() 方法,具体能恢复哪些数据,需要查看其源码。保存和恢复 View 用到了事件委托思想,从下至上,再从上到下。需要注意的是,只有我们为 View 指定了唯一的ID属性(android:id)系统才会自动为其在需要时自动保存和恢复数据。
通过重写onSaveInstanceState()onRestoreInstanceState() 实现自定义的数据恢复机制。
那么 onSaveInstanceState()onRestoreInstanceState() 方法和 Activity 的生命周期的执行顺序是怎么样的?
onSaveInstanceState() 方法是在onStop之前,和onPause没有既定的时序关系, onRestoreInstanceState() 方法是在onStart之后、onResume之前调用的。

Activity启动模式

默认情况下,当我们多次启动同一个Activity时,系统会创建多个实例并把它们一一放入任务栈中,任务栈是一种后进先出的栈结构,每按下back键就会有一个Activity出栈,直到栈空为止。

standard:标准模式

这是系统默认的模式,每次启动一个新的Activity都会重新创建一个新的实例,不管这个实例已经是否存在。这种模式下,如果A启动了B(标准模式),那么B自动进入A所在的任务栈中。

singleTop:栈顶复用模式

此种模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时onNewIntent方法会被调用,通过此方法的参数获取当前请求信息。而且,此Activity的onCreate,onStart不会被调用,因为没有发生改变。

singleTask:栈内复用模式

此种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,系统会回调onNewIntent方法。系统会先寻找是否存在A想要的任务栈,如果不存在,就重建一个任务栈,然后创建A的实例放入新任务栈中;如果存在A想要的任务栈,再查看是否有Activity实例存在,有的话就把该实例调到栈顶,如果实例不存在,则创建A的实例放入任务栈中。下面举三种例子说明此种模式运行机制:

  • 目前任务栈S1中为ABC,Activity D以singleTask模式请求启动,其需要的任务栈为S1,那么系统会创建D的实例,将D放入S1中
  • 目前任务栈S1中为ABC,Activity D以singleTask模式请求启动,其需要的任务栈为S2,那么系统会创建任务栈S2,再将D放入S2中
  • 目前任务栈S1中为ADBC,Activity D以singleTask模式请求启动,其需要的任务栈为S1,那么系统不会创建D的实例,将D切换到栈顶并调用其onNewIntent方法,同时栈内所有在D上面的Activity都需要出栈,最终的S1为AD

singleInstance:单实例模式

这是一种加强的singleTask模式,除了具有singleTask模式的所有特性外,具有此种模式的Activity只能单独位于一个任务栈中。比如Activity A以singleInstance模式启动,系统会为其创建一个新的任务栈,然后A独自运行在该任务栈中,后续的请求均不会创建新的Activity。

任务栈

在启动模式中多次提到Activity的任务栈,默认情况下,所有Activity所需任务栈的名字为应用的包名。此外还有一个参数TaskAffinity,这个参数标识了Activity所需要的任务栈的名字,TaskAffinity属性主要和singleTask模式或者allowTaskReparenting属性配对使用,具体请参考《Android开发艺术探索》P19Android任务和返回栈完全解析,细数那些你所不知道的细节

如何指定Activity启动模式

  • 第一种是通过AndroidManifest.xml 指定:
<activity android:name=".SecondActivity"
    android:launchMode="singleTask"
    android:label="@string/app_name"/> 
  • 第二种是通过在Intent中设置标志位,比如:
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); 

Activity启动过程源码分析

聊完了Activity的生命周期及启动模式,最头疼的部分来了,那就是一个Activity究竟是如何启动的呢?以下篇幅结合源码一探究竟,拨开云雾见青天。在显式调用启动Activity时,我们通过以下代码完成:

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

上述代码便可以启动一个Activity,下面我们便从源头理清Activity的启动流程,当然我们不可能对所有细节描述清楚,需要做的是理清流程,点到为止。

startActivity/startActivityForResult

我们从Activity的startActivity方法开始分析,读源码可知,startActivity方法有好几种重载形式,但最终都调用了startActivityForResult方法,因此我们重点分析startActivityForResult方法:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
    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) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            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 {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
} 

Instrumentation

我们主要关注mParent == null这一部分逻辑,首先,mParent是一个Activity对象,表示该Activity是否由父Activity启动,如果该Activity是第一个被启动的,那么就会调用InstrumentationexecStartActivity方法:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        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是管理Activity的一个工具类,包括创建和启动Activity,Activity的生命周期方法都是由Instrumentation这个类来控制,一个进程中只用一个Instrumentation实例。
execStartActivity是真正启动Activity的操作,下面解释其参数:

  • who : 待启动的Activity对象
  • mMainThread.getApplicationThread() : ApplicationThread对象,也是Binder对象
  • mToken :Binder对象,指向服务端一个ActivityRecord对象
  • target :待启动的Activity对象
  • intent :启动的intent对象
  • requestCode :请求码
  • options :参数

AMS

再回到execStartActivity方法体中,其中可以看到真正实现Activity启动的是ActivityManagerNative.getDefault().startActivity方法。下面列出了ActivityManagerNative.getDefault()的源码:

static public IActivityManager getDefault() {
    return gDefault.get();
}

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in = 
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;                        // 同一进程,返回本地对象stub
    }
    return new ActivityManagerProxy(obj); // 跨进程,返回代理对象
} 

其中声明了一个Singleton封装类,类型是IActivityManager,第一次调用它的get方法它会通过create方法来初始化AMS这个Binder对象。其中在asInterface方法中返回了一个IActivityManager类型对象。
ActivityManagerService(AMS)继承自ActivityManagerNative,而ActivityManagerNative继承自Binder并实现了IActivityManager接口,因此AMS是一个Binder,同时也是IActivityManager的具体实现,ActivityManagerNative.getDefault()其实是一个IActivityManager类型的Binder对象,即AMS。我们理一下上面提到的各种类和接口之间的关系:

public final class ActivityManagerService extends ActivityManagerNative {...}

public abstract class ActivityManagerNative extends Binder implements IActivityManager {...}

public interface IActivityManager extends IInterface {...} 

所以Activity的启动过程转移到AMS中,下面分析AMSstartActivity方法:

public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);

    // Android7.0 Acitivty启动管理类新增ActivityStarter(原本是ActivityStackSupervisor处理该过程)
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, null);
} 

ActivityStarter

上述代码中mActivityStarter是一个ActivityStarter对象,初始化为:

mActivityStarter = new ActivityStarter(this, mStackSupervisor); 

可以看出Activity的启动过程转移到ActivityStarterstartActivityMayWait方法中,startActivityMayWait又调用了startActivityLocked方法:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, Intent intent, String resolvedType,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
        Bundle bOptions, boolean ignoreTargetSecurity, int userId,
        IActivityContainer iContainer, TaskRecord inTask) {

        ...

        // 根据Intent中在系统中找到合适的应用的Activity,如果有多个Activity可选择则弹出界面让用户选择
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

        ...

        int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor,
                resultTo, resultWho, requestCode, callingPid,
                callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                inTask);

        ...

        return res;
    }
} 

startActivityLocked方法又调用startActivityUnchecked方法:

final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
        ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
        TaskRecord inTask) {
    int err = ActivityManager.START_SUCCESS;

    ...

    // 创建ActivityRecord对象
    // ActivityRecord : 在AMS中,用ActivityRecord来作为Activity的记录者,每次启动一个Actvity会有一个对应
    // 的ActivityRecord对象,表示Activity的一个记录
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
            options, sourceRecord);

    ...

    err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true, options, inTask);

    ...

    // 此处Activity对应的Task被移至前台
    postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
    return err;
} 

startActivityUnchecked调用了ActivityStackstartActivityLocked方法和ActivityStackSupervisorresumeFocusedStackTopActivityLocked方法:

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {

    ...

    // ActivityStack的startActivityLocked方法        
    mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);

    if (mDoResume) {
        final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            // If the activity is not focusable, we can't resume it, but still would like to
            // make sure it becomes visible as it starts (this will also trigger entry
            // animation). An example of this are PIP activities.
            // Also, we don't want to resume activities in a task that currently has an overlay
            // as the starting activity just needs to be in the visible paused state until the
            // over is removed.
        } else {
            // ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
        }

        ...
    }

    ...

} 

ActivityStackSupervisor

ActivityStackSupervisorresumeFocusedStackTopActivityLocked方法如下:

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        // 待启动Activity对应的Task为前台栈时,调用该Task对应ActivityStack的resumeTopActivityUncheckedLocked方法
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || r.state != RESUMED) {
        // 否则只是调用此时前台栈的resumeTopActivityUncheckedLocked方法
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
    return false;
} 

ActivityStack

下面进入ActivityStackresumeTopActivityUncheckedLocked方法:

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {

    ...

    result = resumeTopActivityInnerLocked(prev, options);

    ...

    return result;
} 

紧接着又调用了resumeTopActivityInnerLocked方法:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

    ...

    // mResumedActivity指向上一次启动的Activity
    if (mResumedActivity != null) {

        ...

        // 让上一次的Activity进入pause状态
        pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
    }

    if (pausing) {
        ...
        if (next.app != null && next.app.thread != null) {
            // 如果Activity所在App已经启动,则更新Activity所在进程优先级,防止被kill
            mService.updateLruProcessLocked(next.app, true, null);
        }
        ...
    } 

    ...

    if (next.app != null && next.app.thread != null) {
        ...
        if (next.newIntents != null) {
            // 如果Intent不为空,则调用NewIntent传入Intent参数
            next.app.thread.scheduleNewIntent(
                next.newIntents, next.appToken, false /* andPause */);
            ...
        }

        ...

        // Activity已经启动,重新进入前台
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
            mService.isNextTransitionForward(), resumeAnimOptions);
        ...

    } else {
        ...
        // 创建进程,启动Activity,或者已经启动App,启动Activity
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    ...
    return true;
} 

resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisorstartSpecificActivityLocked方法:

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    r.task.stack.setLaunchTime(r);

    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            // 目标Activity所在APP已启动
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }

    // 目标Activity所在APP未启动,通过zygote创建应用进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
} 

startSpecificActivityLocked方法调用了realStartActivityLocked方法:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

    ...

    // 目标Activity所在APP已启动,通过此方法启动目标Activity
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
        new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
        newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

    ...

} 

上面这段代码中,其中app.thread的类型是IApplicationThreadIApplicationThread的声明如下:

public interface IApplicationThread extends IInterface {...} 

IApplicationThread继承了IInterface,所以它是一个Binder类型的接口,IApplicationThread内部包含了大量启动、停止Activity的接口,此外还包含启动和停止服务的接口。
IApplicationThread的实现者就是ActivityThread的内部类ApplicationThread,相关类的继承和实现关系如下所示:

private class ApplicationThread extends ApplicationThreadNative { ... }
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread { ... } 

说了这么多,分析下来不仅累,还容易被绕晕,画张流程图总结下:

Android Activity生命周期,启动模式,启动过程详解

ApplicationThread

绕了一圈,Activity的启动过程还是回到了ApplicationThread中,ApplicationThread通过scheduleLaunchActivity方法启动Activity,源码如下:

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
        int procState, Bundle state, PersistableBundle persistentState,
        List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

    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;
    r.compatInfo = compatInfo;
    r.state = state;
    r.persistentState = persistentState;

    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;

    r.startsNotResumed = notResumed;
    r.isForward = isForward;

    r.profilerInfo = profilerInfo;

    r.overrideConfig = overrideConfig;
    updatePendingConfiguration(curConfig);

    sendMessage(H.LAUNCH_ACTIVITY, r);
} 

其主要实现就是发送一个启动消息交由Handler处理,这个Handler有个特殊的名字叫H(是不是很萌的名字),sendMessage的实现如下:

private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
    if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                    "seq= " + seq);
    Message msg = Message.obtain();
    msg.what = what;
    SomeArgs args = SomeArgs.obtain();
    args.arg1 = obj;
    args.argi1 = arg1;
    args.argi2 = arg2;
    args.argi3 = seq;
    msg.obj = args;
    mH.sendMessage(msg);
} 

H对Activity启动的消息进行处理:

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; 

ActivityThread

从上面代码可以看出,Activity的启动过程又转到ActivityThreadhandleLaunchActivity方法中,其源码如下:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...

    // 此方法中完成Activity生命周期的onCreate和onStart方法
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        // 此方法中完成Activity生命周期的onResume方法
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

        ...
    }

    ...
} 

上述代码中的performLaunchActivity方法最终完成了Activity对象的创建和启动过程,performLaunchActivity这个方法主要完成了以下几件事:

摘自Android开发艺术探索

  1. 从ActivityClientRecord中获取待启动的Activity的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
    r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
            Context.CONTEXT_INCLUDE_CODE);
}

// ComponentName用来定义一个应用程序组件,例如Activity,Service,BroadcastReceiver,ContentProvider
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);
} 
  1. 通过Instrumentation的newActivity方法使用类加载器创建Activity对象
Activity activity = null;
try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    // 通过类加载器来创建Activity对象
    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);
    }
} 
  1. 通过LoadedApk的makeApplication方法来创建Application对象
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    // 先判断Application是否为空,如果Application被创建过,就不会再重复创建,一个应用只有一个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);
        // 通过类加载器创建Application对象
        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);
            }
        }
    }

    ...

    return app;
} 
  1. 创建ContextImpl对象,并通过Activity的attach方法来完成一些重要数据的初始化
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);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
        + r.activityInfo.name + " with config " + config);
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); 

ContextImpl是一个很重要的数据结构,很明显是Context的具体实现,Context中大部分逻辑都是由ContextImpl实现的。ContextImpl通过Activity的attach方法来和Activity建立关联,同时在attach方法中还会完成Window的创建并建立自己和Window的关联,Window接收到外部事件输入后将事件传递给Activity。

  1. 调用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state); 

上述代码中调用Activity的onCreate方法,意味着Activity已经完成了整个启动过程。此外还调用了Activity的onStartOnRestoreInstanceState方法:

activity.performStart();
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); 

总结

至此,整个Activity的启动流程已经分析完了,其中还有很多细节需要打磨:

  • 启动过程中涉及到的类的作用分别是什么,我们并没有深入分析
  • 可以看出,Activity启动最后涉及到Handler消息循环机制,可以参考我的上一篇文章:Android消息机制Handler
  • Activity启动过程中AMS的地位显著,但是进程间通信的具体本质我也没有分析,下一步可以分析下Android IPC机制
  • Android从开机到点击Icon打开APP的过程中涉及到Launcher(它其实也是一个android应用程序)的启动以及APP进程的创建,我们此处没有提及,以后的博客中我也会整理分析
收藏
评论区

相关推荐

Android Activity生命周期,启动模式,启动过程详解
前言 接触过Android开发的同学都知道Activity,Activity作为Android四大组件之一,使用频率高。简单来说Activity提供了一个显示界面,让用户进行各种操作,本文主要分为以下三个部分:Activity的生命周期,启动模式,以及Activity的工作过程。文中大部分篇幅来自《Android开发艺术探索》一书,尽管想多以流程或图
Android中一个Activity关闭另一个Activity或者在一个Activity中关闭多个Activity
前言 最近项目中涉及需要在一个Activity中关闭另一个Activity或者在一个Activity中关闭多个Activity的需求,不涉及到应用的退出。自己首先想了一些方案,同时也查了一些方案,就各个方案比较下优劣。 方案一 广播的方式 这个是最容易想到的,同时也是网上提供最多的。 由于多个Activity要使用,关闭页面
Android通过URL打开Activity
关注公众号 QXF069 为每个 Activity 绑定一个 url 可以方便的让第三方 app 直接打开这些 Activity。也可以方便在 app 内部进行页面跳转,解耦。 背景 举一个常见的案例,假设我们有个产品 A,产品 A 包含 h5 网页端和客户端,当用户在手机打开我们的 h5 网页端的时候,我们会期望如果用户手机安装了我们的客户端,则直接打
Android Fragment生命周期
Fragment 是在 Android 3.0 中引入,用于解决不同屏幕分辨率的设备上 UI 显示、交互的问题。Fragment 有自己的布局,有自己的生命周期,有自己的事件响应。 但 Fragment 又是依赖于 Activity 存在的,你可以把多个 Fragment 嵌入到一个 Activity 中或者多个 Activity 重用一个 Fragmen
Android 面试官精心整理:"五年面试经验
作者:面试官首先呢!做为一个面试官,这几年面过的中高级 Android 开发工程师已经突破了上百人,Failed 的不敢说,但是 Pass 掉的基本是没有看走眼的;眼看年后春招即将来袭,特此赶在年轻整理完毕,谈谈我对 Android 中高级面试的一些看法和体会。 如果,你有更好的看法,希望能在评论区留言,我们一起讨论。一般来说,大部分面试官在面
Android四大组件与进程启动的关系
一. 概述Android系统将进程做得很友好的封装,对于上层app开发者来说进程几乎是透明的. 了解Android的朋友,一定知道Android四大组件,但对于进程可能会相对较陌生. 一个进程里面可以跑多个app, 一个app也可以跑在多个进程里,通过配置Android:process属性来决定所运行在哪个进程。再进一步进程是如何创建的, 可能很多人不知道f
Android深入理解Context(一)Context关联类和Application Context创建过程
Android框架层 Android深入理解Contextcategories: Android框架层本文首发于微信公众号「刘望舒」 前言Context也就是上下文对象,是Android较为常用的类,但是对于Context,很多人都停留在会用的阶段,这个系列会带大家从源码角度来分析Context,从而更加深入的理解它。<!more 1.Context概述Co
Android深入理解Context(二)Activity和Service的Context创建过程
Android框架层 Android深入理解Contextcategories: Android框架层本文首发于微信公众号「刘望舒」 前言上一篇文章我们学习了Context关联类和Application Context的创建过程,这一篇我们接着来学习Activity和Service的Context创建过程。需要注意的是,本篇的知识点会和深入理解四大组件系列的
Android深入四大组件(一)应用程序启动过程(前篇)
Android框架层 Android深入四大组件categories: Android框架层本文首发于微信公众号「后厂技术官」 前言在此前的文章中,我讲过了Android系统启动流程和Android应用进程启动过程,这一篇顺理成章来学习Android 7.0的应用程序的启动过程。分析应用程序的启动过程其实就是分析根Activity的启动过程。<!more 1
Android深入四大组件(一)应用程序启动过程(后篇)
Android框架层 Android深入四大组件categories: Android框架层本文首发于微信公众号「刘望舒」 1.ActivityManageService到ApplicationThread的调用流程AMS的startActivity方法中return了startActivityAsUser方法:<!moreframeworks/base/s
Android深入四大组件(二)Service的启动过程
Android框架层 Android深入四大组件categories: Android框架层本文首发于微信公众号「刘望舒」 前言此前我用较长的篇幅来介绍Android应用程序的启动过程(根Activity的启动过程),这一篇我们接着来分析Service的启动过程。建议阅读此篇文章前,请先阅读和这两篇文章。<!more 1.ContextImpl到Activi
Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)
Android框架层 Android深入四大组件categories: Android框架层本文首发于微信公众号「刘望舒」 前言在几个月前我写了和这两篇文章,它们都是基于Android 7.0,当我开始阅读Android 8.0源码时发现应用程序(根Activity)启动过程照Android 7.0有了一些变化,因此又写下了本篇文章,本篇文章照此前的文章不仅
Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)
Android框架层 Android深入四大组件categories: Android框架层本文首发于微信公众号「刘望舒」 前言在几个月前我写了和这两篇文章,它们都是基于Android 7.0,当我开始阅读Android 8.0源码时发现应用程序(根Activity)启动过程照Android 7.0有了一些变化,因此又写下了本篇文章,本篇文章照此前的文章不仅
Android解析ActivityManagerService(二)ActivityTask和Activity栈管理
Android框架层 Android系统服务 ActivityManagerService Android框架层本文首发于微信公众号「刘望舒」 前言关于AMS,原计划是只写一篇文章来介绍,但是AMS功能繁多,一篇文章的篇幅远远不够。这一篇我们接着来学习与AMS相关的ActivityTask和Activity栈管理。 1.ActivityStackActivi
Android包管理机制(五)APK是如何被解析的
Android框架层 Android包管理机制 Android框架层本文首发于微信公众号「刘望舒」 前言在本系列的前面文章中,我介绍了PackageInstaller的初始化和安装APK过程、PMS处理APK的安装和PMS的创建过程,这些文章中经常会涉及到一个类,那就是PackageParser,它用来在APK的安装过程中解析APK,那么APK是如何被解析的