AMS與Activity的交互

這裏寫圖片描述
上面是Activity典型的生命週期流程圖,基本的就不講了,提兩個問題來求解下
1:當啓動一個新的Activity時,新舊兩個Activity的生命週期執行順序
2:當你在onCreat中調用startActivity或者finish的時候,生命週期執行流程

首先來求解第一個問題,很簡單,建立兩個Activity,每個生命週期上打上log

@Override
protected void onStart() {
   Log.e("xw", "111---onStart");
   super.onStart();
}


@Override
protected void onStart() {
   Log.e("xw", "222---onStart");
   super.onStart();
}

跳轉之後log爲
這裏寫圖片描述
可以看到首先調用了第一個Activity的onPause方法,之後第二個Activity的onCreat,onStart,onResume方法依次執行,最後才輪到第一個Activity的onStop方法。
先不從實現單從產品的角度來講,這種執行順序很有道理,因爲onPause執行後意味着Activity不再接收事件,所以onPause必定要在第二個Activity的onResume方法之前執行,否則會導致有兩個Activity可以接收事件,這顯然不合理。而各種系統都要考慮的就是響應速度,從安卓來講,就是要最快的展示給用戶新的Activity,也就是新的Activity的生命週期要儘早執行,所以,最終結論是,首先終止第一個Activity接收事件的能力,之後展現新的Activity,最後第一個Activity再去進行收尾工作。具體的實現等下再說。
接着是第二個問題,首先看調用startActivity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.e("xw", "111---onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startActivity(new Intent(MainActivity.this, Main2Activity.class));
    }

打印的log爲
這裏寫圖片描述
可以看到完整的執行了整個生命週期,而且第一個onPause首先執行,接着是finish

@Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.e("xw", "111---onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        finish();
    }

這裏寫圖片描述
可以看到只執行了onCreate和與之對應的onDestroy,那麼我們把finish放在onStart中,看看會發生什麼

@Override
    protected void onStart() {
        Log.e("xw", "111---onStart");
        finish();
        super.onStart();
    }

這裏寫圖片描述
可以看到,同樣如此,沒有完整的執行整個生命週期
下面我們開始分析原因
首先我們要知道Activity的生命週期調用是由Framework中的AMS決定的,我們看看到底請求如何從應用傳遞到AMS
startActivity最終都會調用到startActivityForResult這個方法中,我們看看他做了什麼

@Override
    public void startActivityForResult(
            String who, Intent intent, int requestCode, @Nullable Bundle options) {
        Uri referrer = onProvideReferrer();
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, who,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, who, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        cancelInputsAndStartExitTransition(options);
    }

關鍵在於mInstrumentation的execStartActivity方法

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        ......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

其中ActivityManagerNative.getDefault()獲取的就是AMS的代理類,我們可以利用它遠程調用AMS的各種方法,在這裏,我們將調用AMS的startActivity,這樣請求就從應用傳遞給了AMS
接着看看finish方法

public void finish() {
        finish(DONT_FINISH_TASK_WITH_ACTIVITY);
    }

private void finish(int finishTask) {
        if (mParent == null) {
            int resultCode;
            Intent resultData;
            synchronized (this) {
                resultCode = mResultCode;
                resultData = mResultData;
            }
            if (false) Log.v(TAG, "Finishing self: token=" + mToken);
            try {
                if (resultData != null) {
                    resultData.prepareToLeaveProcess(this);
                }
                if (ActivityManagerNative.getDefault()
                        .finishActivity(mToken, resultCode, resultData, finishTask)) {
                    mFinished = true;
                }
            } catch (RemoteException e) {
                // Empty
            }
        } else {
            mParent.finishFromChild(this);
        }
    }

也是利用ActivityManagerNative.getDefault()將請求傳遞給了AMS

AMS收到消息後根據請求內部進行一系列操作,之後也是通過IPC調用,將需要的操作通知應用進程。

應用進程其實就是一個ActivityThread,而負責接收AMS消息的則是ActivityThread的一個內部類ApplicationThread,他也是一個binder,它裏面的方法中很明顯的有幾個涉及基本的生命週期調用

scheduleLaunchActivity
scheduleResumeActivity
schedulePauseActivity
scheduleStopActivity
scheduleDestroyActivity

其中scheduleLaunchActivity適用於新建一個Activity,scheduleResumeActivity適用將已有的Activity重新展示,schedulePauseActivity由於之前所說的原因所以會單獨調用,scheduleStopActivity適用於startActivity時舊的Activity,而scheduleDestroyActivity適用於finish是舊的Activity,可以看到也是除了schedulePauseActivity較爲特殊,也是一一對應的關係。

下面我們看看scheduleLaunchActivity的具體實現

@Override
        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) {
            ......
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

因爲binder的代碼會運行在他開啓的線程中,所以要使用Handler將消息發送到主線程中,利用ActivityThread中H這個Handler來進行處理,看看H的處理方式

case LAUNCH_ACTIVITY: {
     ......
     handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");    
} break;

調用到handleLaunchActivity方法中

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ......
    Activity a = performLaunchActivity(r, customIntent);
    ......
    handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    ......
    }

關鍵的就是這兩個,先看第一句performLaunchActivity

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ......
        } ......
         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);

                ......
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
               ......
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                ......
        return activity;
    }

重要的以下四點:
1:根據傳遞進的參數利用ClassLoader構建Activity類
2:調用Activity的attach的方法,裏面將Activity的各種參數初始化,並且設置了Activity關聯的PhoneWindow類,很重要,但是和現在講的生命週期關係不大
3:mInstrumentation.callActivityOnCreate方法,在裏面Activity調用了我們熟悉的onCreat方法
4:activity.performStart()裏面調用了Activity的onStart方法,當然要調用的首先會判斷mFinished的值,我們再看下前面的finish方法,裏面在將消息發送給AMS後還將mFinished置爲TRUE,這解釋了爲什麼在onCreat調用finish後onStart方法不會被調用到。在調用完onStart之後還會將stopped置爲false,這個將之後用於判斷是否去執行onStop方法
看完performLaunchActivity,我們接着去看看handleResumeActivity方法,從名字就可以看出是用來調用onResume方法的

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ......
        r = performResumeActivity(token, clearHide, reason);
        ......
        ActivityManagerNative.getDefault().activityResumed(token);
    }

public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide, String reason) {
        ......
        if (r != null && !r.activity.mFinished) {
            ......
            r.activity.performResume();
            r.paused = false;
            r.stopped = false;
            ......
        }
        return r;
    }

也會判斷mFinished的值,之後調用onResume。
如果正常情況下的話,scheduleLaunchActivity會使一個新的Activity對象被創建,並且成功調用onCreate,onStart,onResume方法,並將paused 和stopped 值置爲false,最後將成功啓動Activity的消息通知AMS

所以同理scheduleResumeActivity會去執行Activity的onStart和onResume方法,scheduleStopActivity和scheduleDestroyActivity也同樣,拿schedulePauseActivity做個代表再說下,schedulePauseActivity發消息後會執行ActivityThread的handlePauseActivity方法

private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            ......
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
            ......
            ActivityManagerNative.getDefault().activityPaused(token);          
        }
    }

同樣,調用performPauseActivity然後去通知AMS,看看performPauseActivity方法

final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
    }

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
        if (r.paused) {
            if (r.activity.mFinished) {
                // If we are finishing, we won't call onResume() in certain cases.
                // So here we likewise don't want to call onPause() if the activity
                // isn't resumed.
                return null;
            }
        .....
        }
        .....
        performPauseActivityIfNeeded(r, reason);
        ......
    }

首先就告訴我們如果調用了finish但是沒有調過onResume那麼就什麼都不做,直接返回,否則的話就會去調用performPauseActivityIfNeeded,裏面會調用Activity的onPause方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章