天天看點

Android如何安全退出多個Activity

      在做Android App的時候,幾乎每個App都有一個“退出應用”的功能,如何做到完全退出一個App呢?Google了一些文章,都是都是通過List緩存Activity,在需要退出app的時候,疊代activity清單并調用finish方法,這種方案可以達到完全退出App的功能,但是潛在的問題很大,由于Activity被緩存導緻不能被釋放,容易導緻OOM,是以這種方式需要慎用。

下面介紹一種解決方案,利用Activity啟動時的flag屬性來解決此問題,其性能優于通過緩存Activity來完全退出App的方案,隻是這種解決方案需要滿足一些條件(見分析過程)。

實作步驟:

1:建立一個“空”的輔助Activity,在其onCreate方法中調用finish方法。如下:

public class LastActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		finish();
	}
}
           

2:點選“退出App”的按鈕執行以下方法:

findViewById(R.id.quit).setOnClickListener(new OnClickListener() {
	
	@Override
	public void onClick(View v) {
		Intent intent = new Intent(SecondActivity.this,LastActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		SecondActivity.this.startActivity(intent);
		finish();
	}
});
           

通過這兩個步驟可以實作退出整個應用。下面做一個簡單地分析:

測試中使用三個Activity,其執行順序為MainActivity -> SecondActivity -> LastActivity,在SecondActivity中,我們期望點選“退出app”按鈕來實作完全退出App的功能,此時我們将借助一個輔助Activity(LastActivity)。

首先在觸發點選事件後,在onClick方法中執行啟動LastActivity操作。在執行點選事件前我們先檢視任務棧中運作着的Activity,可以通過如下的指令檢視:

adb shell dumpsys activity
           

其結果如下:

Android如何安全退出多個Activity

此時我們可以知道MainActivity跟SecondActivity屬于同一個任務棧,且啟動順序為MainActivity -> SecondActivity。在onClick方法中我們準備啟動LastActivity的時候,其Flag被設定為Intent.FLAG_ACTIVITY_CLEAR_TASK,該flag在android 文檔中的表述為“If set in an Intent passed to 

Context.startActivity()

, this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started.”,其表達的意思為在啟動新的Activity的時候,将清理跟此Activity“相關”的任務棧,此時除了棧中本身的Activity(SecondActivity)都将被清理,然後再啟動Activity(LastActivity)。下面來驗證其是否正确,在LastActivity的onCreate調用finish前加上斷點,然後點選“退出App”按鈕,檢視任務棧的資訊如下:

Android如何安全退出多個Activity

此時我們可以看出,在LastActivity被啟動後,MainActivity被清理了,此時任務棧中隻剩下LastActivity跟SecondActivity。接着運作LastActivity的finish方法,LastActivity退出,然後SecondActivty也退出,此時就退出App了。

上面的方式是所有的Activity都存在同一個任務棧中的情況,對于擁有不同任務棧的不同Activity是否也能真正意義上的完全退出App呢?下面我們将在AndroidManifest.xml檔案中對SecondActivity跟LastActivity中做如下設定,使其位于不同的任務棧中:

<activity
      android:name=".SecondActivity"
      android:launchMode="singleTask"
      android:taskAffinity="com.umeng.social"
     />
<activity 
      android:name=".LastActivity"
      android:launchMode="singleTask"
      android:taskAffinity="com.umeng.social.test" 
     />
           

此時我們檢視任務棧的情況,如下:

Android如何安全退出多個Activity

此時我們可以看見MainActivity跟SecondActivity在不同的任務棧中,此時點選退出App按鈕後,其Activity棧的情況如下:

Android如何安全退出多個Activity

可以看到此時三個Activity都在不同的任務棧中。細心的同學可能已經發現問題了,為什麼LastActivity已經啟動,而MainActivity還沒有被銷毀?是的,這裡就是上面提到的'清理跟此Activity“相關”的任務棧'中“相關”兩字的特殊意義了,這說明在清理Activity時是有條件的,其條件為“被clean的Activity必須跟需要啟動的Activity在同一任務棧中”。由于現在MainActivity、SecondActivity、LastActivity在不同任務棧中,是以Activity不會被清理。執行斷點後續代碼,此時Activity棧中依然存在MainActivity,導緻整個App是不能完全退出的。

是以采用設定falg的方式完全退出App是有條件的,條件為:”整個App的Activity存在同一個任務棧中“或者任務棧模型滿足以下條件:

Android如何安全退出多個Activity

目前對于擁有多個任務棧的情況完全退出App的情況暫時沒有想到比較完美的解決方案,如果有小夥伴知道,請記得留言,謝謝。