在Android系統中,一個application的所有Activity默認有一個相同的affinity(親密關系,相似之處)。也就是說同一個應用程序的的所有Activity傾向於屬於同一個task。但是我們並不能說Android里一個應用程序只有一個任務棧。筆者今天針對當taskAffinity不同時,四種launchMode下在打開一個新的Activity時是否會建立一個新的任務棧做了實驗。
基本的代碼如下:
AndroidManifest.xml:

MainActivity的代碼
package com.example.testlaunchmode; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = (TextView) findViewById(R.id.tv); tv.setText(this.toString()+"\ntaskId="+this.getTaskId()); } public void onJump(View view) { Intent intent = new Intent(this, ActivityTest.class); startActivity(intent); } @Override protected void onNewIntent(Intent intent) { Log.d(TAG, "onNewIntent: intent="+intent); } }
ActivityTest的代碼和MainActivity類似,我就不貼出來了。
1. standard模式:
standard模式是默認模式。在該模式下,Activity可以擁有多個實例,並且這些實例既可以位於同一個task,也可以位於不同的task。
代碼如上面所示,沒有改動,運行結果如下:

點擊button后

可以看出,MainActivity和ActivityTest的taskAffinity並不相同,但是它們被放入同一個任務棧中。
2. singleTop模式
singleTop模式下,在同一個task中,如果存在該Activity的實例,並且該Activity實例位於棧頂(即,該Activity位於前端),則調用startActivity()時,不再創建該Activity的示例;而僅僅只是調用Activity的onNewIntent()。否則的話,則新建該Activity的實例,並將其置於棧頂。
僅僅改動AndroidManifest.xml文件:

運行結果:

點擊button后:

可以看出和standard模式一樣,雖然MainActivity和ActivityTest的taskAffinity不相同,但是它們仍然被放入同一個任務棧中。
3.singleTask模式:
這個模式筆者想先貼代碼和結果:

運行結果:


由上面的結果可以很明顯的看到ActivityTest打開時被放到了一個新的任務棧中,成為新的任務棧的棧底元素,也就是文檔中所說的root activity。這時最新的任務棧成為唯一前台任務棧,而原來的MainActivity所在的任務棧成為眾多后台任務棧中的一個。
實驗做到這里筆者產生了一個新的疑問:如果兩個Activity的taskAffinity相同,還會被這樣嗎?
因此筆者把兩個Activity的taskAffinity改成一樣的再次運行:

結果:


顯然這樣的結果和文檔中給出的-A "singleTask" activity will always be the root activity of the task-是不相符的。后來筆者在文檔中找到這樣一段話(設置了The flag):As described earlier, a new activity is, by default, launched into the task of the activity that called FLAG_ACTIVITY_NEW_TASKstartActivity(). It's pushed onto the same stack as the caller. However, if the Intent object passed to startActivity() contains the FLAG_ACTIVITY_NEW_TASK flag, the system looks for a different task to house the new activity. Often, as the name of the flag implies, it's a new task. However, it doesn't have to be. If there's already an existing task with the same affinity as the new activity, the activity is launched into that task. If not, it begins a new task.
文檔這是紅果果的自相矛盾啊~QUQ
好扒,總結一下是這樣的:
以A啟動B來說
(01) 當A和B的taskAffinity相同時:第一次創建B的實例時,並不會啟動新的task,而是直接將B添加到A所在的task;當B的實例已經存在時,將B所在task中位於B之上的全部Activity都刪除,B就成為棧頂元素,實現跳轉到B的功能。
(02) 當A和B的taskAffinity不同時:第一次創建B的實例時,會啟動新的task,然后將B添加到新建的task中;當B的實例引進存在,將B所在task中位於B之上的全部Activity都刪除,B就成為棧頂元素(也是root Activity),實現跳轉到B的功能。
5. singleInstance模式
singleInstance,顧名思義,是單一實例的意思,即任意時刻只允許存在唯一的Activity實例!
根據文檔,在該模式下,只允許有一個該Activity的實例。當第一次創建該Activity實例時,會新建一個task,並將該Activity添加到該task中。注意:該task只能容納該Activity實例,不會再添加其他的Activity實例!如果該Activity實例已經存在於某個task,則直接跳轉到該task。



顯然這和文檔的描述是相符的~
注意:standard和singleTop模式下被啟動的Activity的實例都可能不只一個,但是singleTask和和singleInstance都是只有一個實例存在的。區別是:
1.A "singleInstance" activity is always at the top of the stack (since it is the only activity in the task).(既是棧頂又是棧底)
2.However, a "singleTask" activity may or may not have other activities above it in the stack。(上面還可能有其它的Activity,也不一定是root Activity)
