Android活動的啟動模式


在實際的項目中,我們應該根據特定的需求為每個活動指定恰當的啟動模式。活動的啟動模式一共有四種,可以在AndroidManifest.xml中通過給<activity>標簽指定android:launchMode屬性來選擇啟動模式。下面我們來逐一介紹:
(1)standard:活動的默認啟動模式,在standard模式下,每當啟動一個新的活動,它就會在返回棧中入棧,並置於棧頂的位置。對於使用standard模式的活動,系統不會在乎這個活動是否已經在返回棧中存在,每次啟動都會創建該活動的一個新的實例。
代碼實例:

 1 @Override
 2 protected void onCreate(Bundle savedInstanceState) {
 3     super.onCreate(savedInstanceState);
 4     setContentView(R.layout.activity_main);
 5 
 6     Log.d(TAG, this.toString());
 7     btn_jump = findViewById(R.id.btn_jump);
 8     btn_jump.setOnClickListener(new View.OnClickListener() {
 9     @Override
10     public void onClick(View v) {
11         Intent intent = new Intent(MainActivity.this,MainActivity.class);
12         startActivity(intent);
13         }
14     });
15 }

運行程序,然后在連續點擊兩次跳轉按鈕,可以看到logcat中打印的信息如下:

從打印的信息我們可以看出,每點擊一次按鈕就會創建一個新的MainActivity實例。此時返回棧中也會存在三個MainActivity的實例,因此你需要連按3次Back鍵才能退出程序。

(2)singleTop:在啟動活動的時候如果發現返回棧的棧頂已經是該活動,則認為可以直接使用它,不會再創建新的活動實例。
修改AndroidManifest.xml中MainActivity的啟動模式,如下所示:

1 <activity 
2 android:name=".MainActivity"
3 android:launchMode="singleTop">
4 <intent-filter>
5 <action android:name="android.intent.action.MAIN" />
6 
7 <category android:name="android.intent.category.LAUNCHER" />
8 </intent-filter>
9 </activity>

運行程序,查看logcat會看到已經創建了一個MainActivity的實例,如圖所示:

但是之后不管你點擊多少次按鈕都不會再有新的打印信息出現,因為目前MainActivity已經處於返回棧的棧頂,每當你想再啟動一個MainActivity時都會直接使用棧頂的活動,所以MainActivity也只會有一個實例,僅按一次Back鍵就可以退出程序。

不過當MainActivity並未處於棧頂位置時,這時再啟動MainActivity,還是會創建新的實例的。

(3)singleTask:當活動的啟動模式指定為singleTask,每次啟動該活動時,系統首先會在返回棧中檢查是否存在該活動的實例,如果發現已經存在則直接使用該實例,並把在這個活動之上的所有活動統統出棧,如果沒有發現就會創建一個新的活動實例。
修改AndroidManifest.xml中MainActivity的啟動模式,如下所示:

1 <activity
2 android:name=".MainActivity"
3 android:launchMode="singleTask">
4 <intent-filter>
5 <action android:name="android.intent.action.MAIN" />
6 
7 <category android:name="android.intent.category.LAUNCHER" />
8 </intent-filter>
9 </activity>

 

然后在MainActivity中添加onRestart()方法,並打印日志:

1 @Override
2 protected void onRestart() {
3     super.onRestart();
4     Log.d("MainActivity","onRestart");
5 }

新建一個activity:JumpActivity,並添加onDestroy()方法,並打印日志:

1 @Override
2 protected void onDestroy() {
3     super.onDestroy();
4     Log.d("JumpActivity","onDestroy");
5 }

在JumpActivity界面布局中添加一個Button控件,添加點擊事件使其跳回MainActivity:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3 xmlns:app="http://schemas.android.com/apk/res-auto"
 4 xmlns:tools="http://schemas.android.com/tools"
 5 android:layout_width="match_parent"
 6 android:layout_height="match_parent"
 7 tools:context=".JumpActivity">
 8 
 9     <Button
10     android:text="跳回去玩一下"
11     android:id="@+id/btn_jump_back"
12     android:layout_width="wrap_content"
13     android:layout_height="wrap_content" />
14 
15 </android.support.constraint.ConstraintLayout>
1 Button btn_jump_back = findViewById(R.id.btn_jump_back);
2 btn_jump_back.setOnClickListener(new View.OnClickListener() {
3     @Override
4     public void onClick(View v) {
5     Intent intent = new Intent(JumpActivity.this,MainActivity.class);
6     startActivity(intent);
7     }
8 });

最后修改Button的點擊事件,使其跳轉到JumpActivity界面:

1 btn_jump.setOnClickListener(new View.OnClickListener() {
2     @Override
3     public void onClick(View v) {
4     Intent intent = new Intent(MainActivity.this,JumpActivity.class);
5     startActivity(intent);
6     }
7 });

運行程序,在MainActivity界面點擊按鈕進入到JumpActivity,然后在按JumpActivity中的返回按鈕,又會進入到MainActivity,查看logcat中的打印信息:

其實從打印信息中就可以看出了,在JumpActivity中啟動MainActivity時,會發現返回棧中已經存在了一個MainActivity實例,並且在JumpActivity的下面,於是JumpActivity會從返回棧中出棧,而MainActivity重新成為了棧頂活動,因此MainActivity中的onRestart()方法和JumpActivity的onDestroy()方法會執行。現在返回棧中只剩下一個MainActivity的實例了,按一下Back鍵就可以退出程序。

(4)singleInstance:指定為singleInstance模式的活動會啟動一個新的返回棧來管理這個活動。
適用場景:共享活動實例的問題
代碼測試:
修改AndroidManifest.xml中JumpActivity的啟動模式:

1 <activity
2 android:name=".JumpActivity"
3 android:launchMode="singleInstance">
4 
5 </activity>

然后修改MainActivity中onCreate()方法的代碼:

1 Log.d("MainActivity", "Task id is "+getTaskId());
2 btn_jump = findViewById(R.id.btn_jump);
3 btn_jump.setOnClickListener(new View.OnClickListener() {
4 @Override
5 public void onClick(View v) {
6     Intent intent = new Intent(MainActivity.this,JumpActivity.class);
7     startActivity(intent);
8     }
9 });

在JumpActivity的onCreate()方法中打印當前返回棧的ID:

1 Log.d("JumpActivity", "Task id is "+getTaskId());

並修改它的點擊事件:

1 btn_jump_back.setOnClickListener(new View.OnClickListener() {
2     @Override
3     public void onClick(View v) {
4         Intent intent = new Intent(JumpActivity.this,ThirdActivity.class);
5         startActivity(intent);
6     }
7 });        

創建一個TiridActivity,同上修改onCreate()方法:

1 Log.d("ThirdActivity","Task id is "+getTaskId());

運行程序:在MainActivity界面點擊按鈕進入JumpActivity,然后再點擊按鈕進入TiridActivity。

查看logcat中的打印信息,如圖所示:

可以看到,JumpActivity的Task id不同於MainActivity和TiridActivity,這說明JumpActivity確實存放在一個單獨的返回棧中,而且這個棧中只有JumpActivity這一個活動。然后我們按下Back鍵進行返回,你會發現TiridActivity直接返回到了MainActivity,再按下Back鍵又會返回到JumpActivity,再按下Back鍵才會退出程序。原因:由於MainActivity和TiridActivity是存放在同一個棧里面的,當在TiridActivity界面按下Back鍵,TiridActivity會從返回棧中出棧,那么MainActivity就會成為棧頂活動顯示在界面上,因此也就出現了從TiridActivity直接返回到了MainActivity的情況。然后在MainActivity界面再次按Back鍵,這時當前的返回棧已經空了,於是顯示了另一個返回棧的棧頂活動,即JumpActivity。最后再按Back鍵,這時所有返回棧都已經空了,也就自然退出了程序。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM