Android Activity生命周期,啟動(dòng)模式,啟動(dòng)過程詳解

系列文章

前言

接觸過Android開發(fā)的同學(xué)都知道Activity,Activity作為Android四大組件之一,使用頻率高。簡單來說Activity提供了一個(gè)顯示界面,讓用戶進(jìn)行各種操作,本文主要分為以下三個(gè)部分:Activity的生命周期,啟動(dòng)模式,以及Activity的工作過程。文中大部分篇幅來自《Android開發(fā)藝術(shù)探索》一書,盡管想多以流程或圖片的形式說明,奈何文筆有限,Android系統(tǒng)整體把握還不夠深入,只能借鑒參考前輩的成果,本文主要目的是幫自己梳理Activity的相關(guān)問題,疏漏之處歡迎指出。

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

Activity生命周期

生命周期

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

Activity生命周期

圖片來源Android開發(fā)者官網(wǎng)

看完了完整的生命周期,我們再分別簡單介紹單個(gè)生命周期含義。

  • onCreate:表示Activity正在被創(chuàng)建,做一些初始化工作,如加載布局文件,對一些變量或者控件進(jìn)行初始化
  • onStart:表示Activity正在啟動(dòng),此時(shí)Activity已經(jīng)可見了,但還無法和用戶交互
  • onResume:表示Activity已經(jīng)在前臺(tái),可以和用戶交互了
  • onPause:表示Activity正在停止,此時(shí)可以進(jìn)行一些輕量級的存儲(chǔ)數(shù)據(jù)和停止動(dòng)畫等工作,但不能太耗時(shí),否則會(huì)影響到新Activity的顯示,Android指定如果onPause在500ms內(nèi)沒有執(zhí)行完畢的話就會(huì)強(qiáng)制關(guān)閉Activity。某些極端情況下,這個(gè)時(shí)候Activity會(huì)回到當(dāng)前Activity,此時(shí)onResume會(huì)被執(zhí)行,很難重現(xiàn)這一情形
  • onStop:表示Activity即將停止,此時(shí)Activity已經(jīng)不可見了,但是Activity對象還存在內(nèi)存中,沒有被銷毀,這個(gè)階段也主要做一些資源回收的工作,不能太耗時(shí)
  • onDestory:表示Activity即將被銷毀,可以做一些回收工作和最終的資源釋放,最后一個(gè)回調(diào)方法
  • onRestart:表示Activity重新啟動(dòng),當(dāng)前Activity從不可見重新變?yōu)榭梢姇r(shí)會(huì)調(diào)用onRestart,這種情況一般是用戶的行為導(dǎo)致的,比如:用戶按Home鍵切換到桌面或者打開了一個(gè)新的Activity

三個(gè)問題

onCreate,onStart和onResume之間的區(qū)別?

  • onCreate時(shí)Activity還不可見,onStart已經(jīng)可見,還不在前臺(tái),onResume已經(jīng)出現(xiàn)在前臺(tái)
  • onCreate方法只在Activity創(chuàng)建時(shí)執(zhí)行一次,而onStart方法在Activity的切換以及按Home鍵返回桌面再切回應(yīng)用的過程中被多次調(diào)用,因此數(shù)據(jù)恢復(fù)在onStart方法中比較合適,onResume方法可以做一些開啟動(dòng)畫和獨(dú)占設(shè)備的操作

onPause,onStop和onDestroy之間的區(qū)別?

  • onPause時(shí)Activity還可見,onStop已經(jīng)不可見,但Activity對象還存在內(nèi)存中,onDestroy后Activity對象就不存在了
  • 內(nèi)存不足時(shí),可能不會(huì)執(zhí)行onStop方法,因此程序狀態(tài)保存,停止動(dòng)畫,存儲(chǔ)數(shù)據(jù)等操作最好放在onPause

切換Activity時(shí)生命周期執(zhí)行順序

假設(shè)當(dāng)前Activity為A,此時(shí)用戶打開Activity B,那么A和B的生命周期的執(zhí)行順序?yàn)椋?/p>

Activity跳轉(zhuǎn)生命周期.png

為了驗(yàn)證生命周期執(zhí)行順序,我們寫個(gè)例子實(shí)測,MainActivity中單擊按鈕跳轉(zhuǎn)到SecondActivity,然后在相應(yīng)的生命周期中輸出日志,如下:

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");
    }
}

日志結(jié)果如下:

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

那么為什么會(huì)有這樣的生命周期執(zhí)行順序呢?Android官方文檔對onPause的解釋為:不能在onPause中做重量級的操作,因?yàn)楸仨歰nPause執(zhí)行完成以后新Activity才能Resume,同時(shí)我在分析Activity啟動(dòng)源過程中碼也得到了相同結(jié)論。

Activity保存狀態(tài)

當(dāng) Activity 暫停或停止時(shí),Activity 的狀態(tài)會(huì)得到保留。因?yàn)楫?dāng) Activity 暫停或停止時(shí),Activity 對象仍保留在內(nèi)存中 ,有關(guān)其成員和當(dāng)前狀態(tài)的所有信息仍處于活動(dòng)狀態(tài)。
但是當(dāng)系統(tǒng)的配置發(fā)生變化(屏幕旋轉(zhuǎn),語言變換等)時(shí),Activity 被銷毀,系統(tǒng)回調(diào) onSaveInstanceState() 方法對有關(guān) Activity 狀態(tài)的信息進(jìn)行保存,系統(tǒng)會(huì)向該方法傳遞一個(gè) Bundle,可以在其中使用 putString()putInt() 等方法以名稱-值對形式保存有關(guān) Activity 狀態(tài)的信息。當(dāng) Activity 重建時(shí)將 Bundle 同時(shí)傳遞給 onCreate()onRestoreInstanceState() 方法,使用上述任一方法從 Bundle 提取保存的數(shù)據(jù)并恢復(fù)該 Activity 狀態(tài)。

Activity保存狀態(tài)

圖片來源Android開發(fā)者官網(wǎng)

onSaveInstanceState()onRestoreInstanceState() 方法中,系統(tǒng)自動(dòng)為我們做了一定的恢復(fù)工作,布局中的每個(gè) View 調(diào)用自己的 onSaveInstanceState() 方法,讓每個(gè)視圖都能保存自身需保存的信息。
每個(gè) View 都有 onSaveInstanceState()onRestoreInstanceState() 方法,具體能恢復(fù)哪些數(shù)據(jù),需要查看其源碼。保存和恢復(fù) View 用到了事件委托思想,從下至上,再從上到下。需要注意的是,只有我們?yōu)?View 指定了唯一的ID屬性(android:id)系統(tǒng)才會(huì)自動(dòng)為其在需要時(shí)自動(dòng)保存和恢復(fù)數(shù)據(jù)。
通過重寫onSaveInstanceState()onRestoreInstanceState() 實(shí)現(xiàn)自定義的數(shù)據(jù)恢復(fù)機(jī)制。
那么 onSaveInstanceState()onRestoreInstanceState() 方法和 Activity 的生命周期的執(zhí)行順序是怎么樣的?
onSaveInstanceState() 方法是在onStop之前,和onPause沒有既定的時(shí)序關(guān)系, onRestoreInstanceState() 方法是在onStart之后、onResume之前調(diào)用的。

Activity啟動(dòng)模式

默認(rèn)情況下,當(dāng)我們多次啟動(dòng)同一個(gè)Activity時(shí),系統(tǒng)會(huì)創(chuàng)建多個(gè)實(shí)例并把它們一一放入任務(wù)棧中,任務(wù)棧是一種后進(jìn)先出的棧結(jié)構(gòu),每按下back鍵就會(huì)有一個(gè)Activity出棧,直到棧空為止。

standard:標(biāo)準(zhǔn)模式

這是系統(tǒng)默認(rèn)的模式,每次啟動(dòng)一個(gè)新的Activity都會(huì)重新創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例已經(jīng)是否存在。這種模式下,如果A啟動(dòng)了B(標(biāo)準(zhǔn)模式),那么B自動(dòng)進(jìn)入A所在的任務(wù)棧中。

singleTop:棧頂復(fù)用模式

此種模式下,如果新Activity已經(jīng)位于任務(wù)棧的棧頂,那么此Activity不會(huì)被重新創(chuàng)建,同時(shí)onNewIntent方法會(huì)被調(diào)用,通過此方法的參數(shù)獲取當(dāng)前請求信息。而且,此Activity的onCreate,onStart不會(huì)被調(diào)用,因?yàn)闆]有發(fā)生改變。

singleTask:棧內(nèi)復(fù)用模式

此種模式下,只要Activity在一個(gè)棧中存在,那么多次啟動(dòng)此Activity都不會(huì)重新創(chuàng)建實(shí)例,系統(tǒng)會(huì)回調(diào)onNewIntent方法。系統(tǒng)會(huì)先尋找是否存在A想要的任務(wù)棧,如果不存在,就重建一個(gè)任務(wù)棧,然后創(chuàng)建A的實(shí)例放入新任務(wù)棧中;如果存在A想要的任務(wù)棧,再查看是否有Activity實(shí)例存在,有的話就把該實(shí)例調(diào)到棧頂,如果實(shí)例不存在,則創(chuàng)建A的實(shí)例放入任務(wù)棧中。下面舉三種例子說明此種模式運(yùn)行機(jī)制:

  • 目前任務(wù)棧S1中為ABC,Activity D以singleTask模式請求啟動(dòng),其需要的任務(wù)棧為S1,那么系統(tǒng)會(huì)創(chuàng)建D的實(shí)例,將D放入S1中
  • 目前任務(wù)棧S1中為ABC,Activity D以singleTask模式請求啟動(dòng),其需要的任務(wù)棧為S2,那么系統(tǒng)會(huì)創(chuàng)建任務(wù)棧S2,再將D放入S2中
  • 目前任務(wù)棧S1中為ADBC,Activity D以singleTask模式請求啟動(dòng),其需要的任務(wù)棧為S1,那么系統(tǒng)不會(huì)創(chuàng)建D的實(shí)例,將D切換到棧頂并調(diào)用其onNewIntent方法,同時(shí)棧內(nèi)所有在D上面的Activity都需要出棧,最終的S1為AD

singleInstance:單實(shí)例模式

這是一種加強(qiáng)的singleTask模式,除了具有singleTask模式的所有特性外,具有此種模式的Activity只能單獨(dú)位于一個(gè)任務(wù)棧中。比如Activity A以singleInstance模式啟動(dòng),系統(tǒng)會(huì)為其創(chuàng)建一個(gè)新的任務(wù)棧,然后A獨(dú)自運(yùn)行在該任務(wù)棧中,后續(xù)的請求均不會(huì)創(chuàng)建新的Activity。

任務(wù)棧

在啟動(dòng)模式中多次提到Activity的任務(wù)棧,默認(rèn)情況下,所有Activity所需任務(wù)棧的名字為應(yīng)用的包名。此外還有一個(gè)參數(shù)TaskAffinity,這個(gè)參數(shù)標(biāo)識(shí)了Activity所需要的任務(wù)棧的名字,TaskAffinity屬性主要和singleTask模式或者allowTaskReparenting屬性配對使用,具體請參考《Android開發(fā)藝術(shù)探索》P19Android任務(wù)和返回棧完全解析,細(xì)數(shù)那些你所不知道的細(xì)節(jié)

如何指定Activity啟動(dòng)模式

  • 第一種是通過AndroidManifest.xml 指定:
<activity android:name=".SecondActivity"
    android:launchMode="singleTask"
    android:label="@string/app_name"/>
  • 第二種是通過在Intent中設(shè)置標(biāo)志位,比如:
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Activity啟動(dòng)過程源碼分析

聊完了Activity的生命周期及啟動(dòng)模式,最頭疼的部分來了,那就是一個(gè)Activity究竟是如何啟動(dòng)的呢?以下篇幅結(jié)合源碼一探究竟,撥開云霧見青天。在顯式調(diào)用啟動(dòng)Activity時(shí),我們通過以下代碼完成:

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

上述代碼便可以啟動(dòng)一個(gè)Activity,下面我們便從源頭理清Activity的啟動(dòng)流程,當(dāng)然我們不可能對所有細(xì)節(jié)描述清楚,需要做的是理清流程,點(diǎn)到為止。

startActivity/startActivityForResult

我們從Activity的startActivity方法開始分析,讀源碼可知,startActivity方法有好幾種重載形式,但最終都調(diào)用了startActivityForResult方法,因此我們重點(diǎn)分析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

我們主要關(guān)注mParent == null這一部分邏輯,首先,mParent是一個(gè)Activity對象,表示該Activity是否由父Activity啟動(dòng),如果該Activity是第一個(gè)被啟動(dòng)的,那么就會(huì)調(diào)用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);
        // 檢查啟動(dòng)Activity的結(jié)果
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

Instrumentation是管理Activity的一個(gè)工具類,包括創(chuàng)建和啟動(dòng)Activity,Activity的生命周期方法都是由Instrumentation這個(gè)類來控制,一個(gè)進(jìn)程中只用一個(gè)Instrumentation實(shí)例。
execStartActivity是真正啟動(dòng)Activity的操作,下面解釋其參數(shù):

  • who : 待啟動(dòng)的Activity對象
  • mMainThread.getApplicationThread() : ApplicationThread對象,也是Binder對象
  • mToken :Binder對象,指向服務(wù)端一個(gè)ActivityRecord對象
  • target :待啟動(dòng)的Activity對象
  • intent :啟動(dòng)的intent對象
  • requestCode :請求碼
  • options :參數(shù)

AMS

再回到execStartActivity方法體中,其中可以看到真正實(shí)現(xiàn)Activity啟動(dòng)的是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;                        // 同一進(jìn)程,返回本地對象stub
    }
    return new ActivityManagerProxy(obj); // 跨進(jìn)程,返回代理對象
}

其中聲明了一個(gè)Singleton封裝類,類型是IActivityManager,第一次調(diào)用它的get方法它會(huì)通過create方法來初始化AMS這個(gè)Binder對象。其中在asInterface方法中返回了一個(gè)IActivityManager類型對象。
ActivityManagerService(AMS)繼承自ActivityManagerNative,而ActivityManagerNative繼承自Binder并實(shí)現(xiàn)了IActivityManager接口,因此AMS是一個(gè)Binder,同時(shí)也是IActivityManager的具體實(shí)現(xiàn),ActivityManagerNative.getDefault()其實(shí)是一個(gè)IActivityManager類型的Binder對象,即AMS。我們理一下上面提到的各種類和接口之間的關(guān)系:

public final class ActivityManagerService extends ActivityManagerNative {...}

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

public interface IActivityManager extends IInterface {...}

所以Activity的啟動(dòng)過程轉(zhuǎn)移到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啟動(dòng)管理類新增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是一個(gè)ActivityStarter對象,初始化為:

mActivityStarter = new ActivityStarter(this, mStackSupervisor);

可以看出Activity的啟動(dòng)過程轉(zhuǎn)移到ActivityStarterstartActivityMayWait方法中,startActivityMayWait又調(diào)用了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) {
        
        ...
        
        // 根據(jù)Intent中在系統(tǒng)中找到合適的應(yīng)用的Activity,如果有多個(gè)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方法又調(diào)用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;
    
    ...
    
    // 創(chuàng)建ActivityRecord對象
    // ActivityRecord : 在AMS中,用ActivityRecord來作為Activity的記錄者,每次啟動(dòng)一個(gè)Actvity會(huì)有一個(gè)對應(yīng)
    // 的ActivityRecord對象,表示Activity的一個(gè)記錄
    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對應(yīng)的Task被移至前臺(tái)
    postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
    return err;
}

startActivityUnchecked調(diào)用了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)) {
        // 待啟動(dòng)Activity對應(yīng)的Task為前臺(tái)棧時(shí),調(diào)用該Task對應(yīng)ActivityStack的resumeTopActivityUncheckedLocked方法
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || r.state != RESUMED) {
        // 否則只是調(diào)用此時(shí)前臺(tái)棧的resumeTopActivityUncheckedLocked方法
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
    return false;
}

ActivityStack

下面進(jìn)入ActivityStackresumeTopActivityUncheckedLocked方法:

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    
    ...
    
    result = resumeTopActivityInnerLocked(prev, options);
    
    ...
    
    return result;
}

緊接著又調(diào)用了resumeTopActivityInnerLocked方法:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
    ...
    
    // mResumedActivity指向上一次啟動(dòng)的Activity
    if (mResumedActivity != null) {
    
        ...
        
        // 讓上一次的Activity進(jìn)入pause狀態(tài)
        pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
    }
    
    if (pausing) {
        ...
        if (next.app != null && next.app.thread != null) {
            // 如果Activity所在App已經(jīng)啟動(dòng),則更新Activity所在進(jìn)程優(yōu)先級,防止被kill
            mService.updateLruProcessLocked(next.app, true, null);
        }
        ...
    } 
    
    ...

    if (next.app != null && next.app.thread != null) {
        ...
        if (next.newIntents != null) {
            // 如果Intent不為空,則調(diào)用NewIntent傳入Intent參數(shù)
            next.app.thread.scheduleNewIntent(
                next.newIntents, next.appToken, false /* andPause */);
            ...
        }
        
        ...
        
        // Activity已經(jīng)啟動(dòng),重新進(jìn)入前臺(tái)
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
            mService.isNextTransitionForward(), resumeAnimOptions);
        ...
        
    } else {
        ...
        // 創(chuàng)建進(jìn)程,啟動(dòng)Activity,或者已經(jīng)啟動(dòng)App,啟動(dòng)Activity
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    ...
    return true;
}

resumeTopActivityInnerLocked方法又調(diào)用了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);
            }
            // 目標(biāo)Activity所在APP已啟動(dòng)
            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.
    }
    
    // 目標(biāo)Activity所在APP未啟動(dòng),通過zygote創(chuàng)建應(yīng)用進(jìn)程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

startSpecificActivityLocked方法調(diào)用了realStartActivityLocked方法:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            
    ...
    
    // 目標(biāo)Activity所在APP已啟動(dòng),通過此方法啟動(dòng)目標(biāo)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,所以它是一個(gè)Binder類型的接口,IApplicationThread內(nèi)部包含了大量啟動(dòng)、停止Activity的接口,此外還包含啟動(dòng)和停止服務(wù)的接口。
IApplicationThread的實(shí)現(xiàn)者就是ActivityThread的內(nèi)部類ApplicationThread,相關(guān)類的繼承和實(shí)現(xiàn)關(guān)系如下所示:

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

說了這么多,分析下來不僅累,還容易被繞暈,畫張流程圖總結(jié)下:

image

圖片參考Android Launcher 啟動(dòng) Activity 的工作過程

ApplicationThread

繞了一圈,Activity的啟動(dòng)過程還是回到了ApplicationThread中,ApplicationThread通過scheduleLaunchActivity方法啟動(dòng)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);
}

其主要實(shí)現(xiàn)就是發(fā)送一個(gè)啟動(dòng)消息交由Handler處理,這個(gè)Handler有個(gè)特殊的名字叫H(是不是很萌的名字),sendMessage的實(shí)現(xiàn)如下:

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啟動(dòng)的消息進(jìn)行處理:

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的啟動(dòng)過程又轉(zhuǎn)到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對象的創(chuàng)建和啟動(dòng)過程,performLaunchActivity這個(gè)方法主要完成了以下幾件事:

摘自Android開發(fā)藝術(shù)探索

  1. 從ActivityClientRecord中獲取待啟動(dòng)的Activity的組件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
    r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
            Context.CONTEXT_INCLUDE_CODE);
}
 
// ComponentName用來定義一個(gè)應(yīng)用程序組件,例如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方法使用類加載器創(chuàng)建Activity對象
Activity activity = null;
try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    // 通過類加載器來創(chuàng)建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方法來創(chuàng)建Application對象
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    // 先判斷Application是否為空,如果Application被創(chuàng)建過,就不會(huì)再重復(fù)創(chuàng)建,一個(gè)應(yīng)用只有一個(gè)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);
        // 通過類加載器創(chuàng)建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 {
            // 調(diào)用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. 創(chuàng)建ContextImpl對象,并通過Activity的attach方法來完成一些重要數(shù)據(jù)的初始化
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是一個(gè)很重要的數(shù)據(jù)結(jié)構(gòu),很明顯是Context的具體實(shí)現(xiàn),Context中大部分邏輯都是由ContextImpl實(shí)現(xiàn)的。ContextImpl通過Activity的attach方法來和Activity建立關(guān)聯(lián),同時(shí)在attach方法中還會(huì)完成Window的創(chuàng)建并建立自己和Window的關(guān)聯(lián),Window接收到外部事件輸入后將事件傳遞給Activity。

  1. 調(diào)用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state);

上述代碼中調(diào)用Activity的onCreate方法,意味著Activity已經(jīng)完成了整個(gè)啟動(dòng)過程。此外還調(diào)用了Activity的onStartOnRestoreInstanceState方法:

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

總結(jié)

至此,整個(gè)Activity的啟動(dòng)流程已經(jīng)分析完了,其中還有很多細(xì)節(jié)需要打磨:

  • 啟動(dòng)過程中涉及到的類的作用分別是什么,我們并沒有深入分析
  • 可以看出,Activity啟動(dòng)最后涉及到Handler消息循環(huán)機(jī)制,可以參考我的上一篇文章:Android消息機(jī)制Handler
  • Activity啟動(dòng)過程中AMS的地位顯著,但是進(jìn)程間通信的具體本質(zhì)我也沒有分析,下一步可以分析下Android IPC機(jī)制
  • Android從開機(jī)到點(diǎn)擊Icon打開APP的過程中涉及到Launcher(它其實(shí)也是一個(gè)android應(yīng)用程序)的啟動(dòng)以及APP進(jìn)程的創(chuàng)建,我們此處沒有提及,以后的博客中我也會(huì)整理分析

參考信息

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。