文章目錄
- Activity 的啟動模式
- standard
- singleTop
- singleTask
- singleInstance
- 技巧
- 了解當前界面是哪個 Activity
- 隨時隨地退出程序
- 啟動活動的最佳寫法
Activity 的啟動模式
- standard:默認的啟動方式,每次啟動一個活動都會重新創建
- singleTop:如果該活動處于棧頂,則不會創建新活動,不處于棧頂則創建新活動
- singleTask:如果返回棧中存在該活動,那么將該活動之上的所有活動統統出棧,將該活動置于棧頂,如果不存在該活動則創建
- singleInstance:會重新啟用一個新的返回棧來創建該活動,通常用于共享活動的實例
standard
standard
是 Activity 默認的啟動模式,在不進行顯式指定的情況下,都使用這種模式。
在本模式下,每當啟動一個新的活動,系統不會確認返回棧中是否已存在這個活動,而是直接創建該活動的一個新的實例并入棧。
singleTop
如果啟動活動時發現返回棧棧頂已經是這個活動,則認為可以直接使用它,不會創建新的實例。
在 AndroidManifest.xml
中添加如下配置:
singleTask
每次啟動該活動時,系統首先會在返回棧中檢查是否存在該活動的實例:
- 如果發現已經存在則直接使用該實例,并把在這個活動之上的活動統統出棧;
- 如果沒有就創建新的實例。
舉個例子:
- 我們為 FirstActivity 配置 singleTask ;
- 然后在 FirstActivity 的 Button 上啟動 SecondActivity;
- 然后 SecondActivity 的 Button 上回到 FirstActivity。
我們可以得到這樣的推斷:
- 在 SecondActivity 中啟動 FirstActivity 時,會發現返回棧中已經存在一個 FirstActivity 的實例;
- 于是 SecondActivity 會從返回棧中出棧,而 FirstActivity 重新成為了棧頂活動;
- 因此 FirstActivity 的 onRestart()方法 和 SecondActivity 的 onDestroy() 方法會得到執行。
singleInstance
在本模式下,活動會啟用一個新的返回棧來管理(如果 singleTask 模式指定了不同的 taskAffinity,也會啟動一個新的返回棧)。如果我們想實現其他程序和我們的程序可以共享某個活動的實例,就可以用 singleInstance 模式創建一個單獨的返回棧來管理這個活動,以此實現讓任意應用程序都可以調用該活動。
舉個例子:
- FirstActivity 通過 Button 跳轉到 SecondActivity;
- SecondActivity 通過 Button 跳轉到 ThirdActivity,且修改 SecondActivity 的啟動模式為
singleInstance
:
<activity android:name=".SecondActivity" android:launchMode="singleInstance">
倘若我們通過 log
來監測三個活動分屬的返回棧,我們會發現:
SecondActivity
是存放在一個單獨的返回棧里的。
而在 ThirdActivity 中按 Back
鍵,那么會直接返回到 FirstActivity,再按下返回鍵會回到 SecondActivity,再按下返回鍵才會退出程序。
原理很簡單:
- 由于 FirstActivity 和 ThirdActivity 是存放在同一個返回棧里的,當在 ThirdActivity 的界面按下
Back
鍵, ThirdActivity 會從返回棧中出棧,那么 FirstActivity 就成為了棧頂活動顯示在界面上。 - 然后在 FirstActivity 界面再次按下
Back
鍵,這時當前的返回棧已經空了,于是就顯示了另一個返回棧的棧頂活動,即 SecondActivity。 - 最后再次按下
Back
鍵,這時所有返回棧都已經空了,也就自然退出了程序。
技巧
了解當前界面是哪個 Activity
新建一個普通 java
類 —— BaseActivity :
public class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);Log.d("BaseActivity", getClass().getSimpleName());}
}
然后讓每個活動類都改為繼承自 BaseActivity,這樣就可以在 LogCat
中看到當前類名。
隨時隨地退出程序
當在程序運行中的一個活動,要退出可能會需要按多次 Back
鍵(按 Home
鍵只是把程序掛起,并沒有退出程序。),所以需要一個直接退出活動的方法。
新建一個 ActivityCollector 類作為活動管理器:
public class ActivityCollector {public static List<Activity> activities = new ArrayList<Activity>();public static void addActivity(Activity activity){ // 用于向 List 中添加一個 Activityactivities.add(activity);}public static void removeActivity(Activity activity){ // 用于從 List 中刪除一個 Activityactivities.remove(activity);}public static void finishAll(){ // 用于將 List 中存儲的所有活動全部銷毀for (Activity activity : activities)if (!activity.isFinishing())activity.finish();}
}
接下來修改 BaseActivity:
public class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);Log.d("BaseActivity", getClass().getSimpleName());ActivityCollector.addActivity(this);// 將當前正在創建的活動添加到活動管理器 ActivityCollector 里}@Overrideprotected void onDestroy(){super.onDestroy();ActivityCollector.removeActivity(this);// 將一個馬上要銷毀的活動從管理器 ActivityCollector 中移除}
}
以后,不管想在什么地方退出程序,只需要 ActivityCollector.finishAll()
就可以了。
保險起見也可以在銷毀所有活動后殺掉當前進程,以保證程序完全退出:
android.os.Process.killProcess(android.os.Process.myPid());
killProcess()
方法用于殺掉一個進程,它接收一個進程 id
參數,通過 myPid()
方法來獲得當前程序的進程 id
。需要注意的是 killProcess()
方法只能用于殺掉當前程序的進程,我們不能使用這個方法去殺掉其他程序。
啟動活動的最佳寫法
之前啟動的方法是構建一個新的 Intent
,然后調用 startActivity()
或者 startActivityForResult()
來啟動活動。如果 SecondActivity 需要用到兩個字符串參數,那么 FirstActivity 可能會寫成下面這樣:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data1", s1);
intent.putExtra("extra_data2", s2);
startActivity(intent);
這樣雖然可以,但是在 SecondActivity 是一個黑盒子時,是會出現問題的。可以修改 SecondActivity 的代碼:
public static void actionStart(Context context, String s1, String s2){Intent intent = new Intent(context, SecondActivity.class);intent.putExtra("extra_data1", s1);intent.putExtra("extra_data2", s2);context.startActivity(intent);
}
和以往不同,在 actionStart()
方法中完成了 Intent
的構建,而非 onClick()
方法,所有 SecondActivity 中需要的數據都是通過 actionStart()
方法的參數傳遞過來的,然后把它們存儲到 Intent
中,最后調用 startActivity()
方法啟動。
這樣在 onClick()
方法中只需一行代碼即可啟動 SecondActivity :
button1.setOnclickListener(new OnclickListener() {@Overridepublic void onclick(View v) {SecondActivity.actionStart(FirstActivity.this, "data1", "data2");}
});