首先需要知道,一鍵退出app要實(shí)現(xiàn)兩個(gè)結(jié)果;
1.Activity退出
2.進(jìn)程結(jié)束
我們先看"Activity的退出",大概有以下幾種方法可以實(shí)現(xiàn)Activity的退出.
方法1:使用BroadcastReceiver.
?????? 1.1寫一個(gè)類集成BroadCastReceiver,重寫onReceiver方法,方法里面調(diào)用finish方法
?????? 1.2 在每一個(gè)activity里面注冊(cè)廣播,并且在Actviity銷毀的時(shí)候取消注冊(cè)廣播.
???? 1.3 在需要退出app的地方,發(fā)送廣播即可.
優(yōu)點(diǎn):應(yīng)用場景廣泛:兼顧單 / 多任務(wù)棧 & 多啟動(dòng)模式的情況
缺點(diǎn): 需要在每個(gè) Activity 里注冊(cè)廣播接收器
方法2:利用Activity的啟動(dòng)模式,singleTask模式
singletask模式:單一任務(wù)模式,若該Activity實(shí)例在棧中存在,那么將會(huì)將其他Activity實(shí)例從棧中移除.,.
???? 2.1 將 App的入口 Activity 設(shè)置成 SingleTask 啟動(dòng)模式
???? 2.2 在入口 Activity重寫 onNewIntent(),根據(jù)傳來的標(biāo)志決定是否退出;
????????????????????????? @Override
?????????????????? protected void onNewIntent(Intent intent) {
??????????????????????????? super.onNewIntent(intent);
?????????????????????????????? if (intent != null) {
??????????????????????????? // 是否退出App的標(biāo)識(shí)
???????????????????????????? boolean isExitApp = intent.getBooleanExtra("exit", false);
?????????????????????????????? if (isExitApp) {
????????????????????????? // 關(guān)閉自身
??????????????????????????? this.finish();
??????????? ? ? ?? }
???? ? ?? ?? }
???? }
?? 2.3 在需要退出時(shí)調(diào)用 exitApp()
??????????????????? private void exitApp() {
?????????????????? Intent intent = new Intent(context, MainActivity.class);
?????????????????????? intent.putExtra("exit", true);
???????????????????? context.startActivity(intent);
??????????????????????? // 結(jié)束進(jìn)程
?????????????????????? // System.exit(0);
}
???? ? ? ? ? ? ?? 優(yōu)點(diǎn): 使用簡單 & 方便
????????? ? ? ? ? 缺點(diǎn): 規(guī)定 App的入口Activity采用SingleTask啟動(dòng)模式
????????????????? 使用范圍局限:只能結(jié)束當(dāng)前任務(wù)棧的Activity,若出現(xiàn)多任務(wù)棧(即采用SingleInstance啟動(dòng)模式)則無法處理
??????? ? ? 應(yīng)用場景
???????????? Activity單任務(wù)棧
方法三: 利用Activity啟動(dòng)標(biāo)記位
Intent.FLAG_ACTIVITY_CLEAR_TOP:銷毀目標(biāo)Activity和它之上的所有Activity,重新創(chuàng)建目標(biāo)Activity
Intent.FLAG_ACTIVITY_SINGLE_TOP:若啟動(dòng)的Activity位于任務(wù)棧棧頂,那么此Activity的實(shí)例就不會(huì)重建,而是重用棧頂?shù)膶?shí)例( 調(diào)用onNewIntent())
?? 3.1:在MainActivity 中設(shè)置 重寫 onNewIntent()
? 3.2在需要退出的地方啟動(dòng)Macitivty并且設(shè)置標(biāo)記位.
Intent intent = new Intent();
intent.setClass(Activity2.this, MainActivity.class);
// 設(shè)置標(biāo)記位
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// 步驟1:該標(biāo)記位作用:銷毀目標(biāo)Activity和它之上的所有Activity,重新創(chuàng)建目標(biāo)Activity
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// 步驟2:若啟動(dòng)的Activity位于任務(wù)棧棧頂,那么此Activity的實(shí)例就不會(huì)重建,而是重用棧頂?shù)膶?shí)例( 調(diào)用實(shí)例的 onNewIntent() )
// 在步驟1中:MainActivity的上層的Activity2會(huì)被銷毀,此時(shí)MainActivity位于棧頂;由于步驟2的設(shè)置,所以不會(huì)新建MainActivity而是重用棧頂?shù)膶?shí)例&調(diào)用實(shí)onNewIntent()
// 傳入自己設(shè)置的退出App標(biāo)識(shí)
intent.putExtra("exit", true);
startActivity(intent);
優(yōu)點(diǎn):使用簡單
缺點(diǎn):只能結(jié)束當(dāng)前任務(wù)棧的actvitiy,若出現(xiàn)多任務(wù)棧則無法處理.
方法四:通過系統(tǒng)任務(wù)棧
通過 ActivityManager 獲取當(dāng)前系統(tǒng)的任務(wù)棧 & 把棧內(nèi)所有Activity逐個(gè)退出.
// 1. 通過Context獲取ActivityManager
ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
// 2. 通過ActivityManager獲取任務(wù)棧
List appTaskList = activityManager.getAppTasks();
// 3. 逐個(gè)關(guān)閉Activity
for (ActivityManager.AppTask appTask : appTaskList) {
appTask.finishAndRemoveTask();
}
// 4. 結(jié)束進(jìn)程
// System.exit(0);
缺點(diǎn):只能結(jié)束當(dāng)前activity的任務(wù)棧,若有多個(gè)任務(wù)棧,則無法退出.
優(yōu)點(diǎn):使用簡單.
方法五:通過記錄保存activity實(shí)例
通過在Application子類中建立一個(gè) Activity鏈表:保存正在運(yùn)行的Activity實(shí)例;當(dāng)需要一鍵退出App時(shí)把鏈表內(nèi)所有Activity實(shí)例逐個(gè)退出即可(其實(shí)我個(gè)人認(rèn)為使用list集合也可以)
5.1:在BaseApplication類的子類里建立Activity鏈表
public class Carson_BaseApplicaiton extends Application {
// 此處采用 LinkedList作為容器,增刪速度快
public static LinkedList activityLinkedList;
@Override
public void onCreate() {
super.onCreate();
activityLinkedList = new LinkedList<>();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated: " + activity.getLocalClassName());
activityLinkedList.add(activity);
// 在Activity啟動(dòng)時(shí)(onCreate()) 寫入Activity實(shí)例到容器內(nèi)
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.d(TAG, "onActivityDestroyed: " + activity.getLocalClassName());
activityLinkedList.remove(activity);
// 在Activity結(jié)束時(shí)(Destroyed()) 寫出Activity實(shí)例
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
});
}
public ?void exitApp() {
Log.d(TAG, "容器內(nèi)的Activity列表如下 ");
// 先打印當(dāng)前容器內(nèi)的Activity列表
for (Activity activity : activityLinkedList) {
Log.d(TAG, activity.getLocalClassName());
}
Log.d(TAG, "正逐步退出容器內(nèi)所有Activity");
// 逐個(gè)退出Activity
for (Activity activity : activityLinkedList) {
activity.finish();
}
// ?結(jié)束進(jìn)程
// System.exit(0);
}
}
// 記得在Manifest.xml中添加
android:name=".Carson_BaseApplicaiton"
....
步驟2:需要一鍵退出 App 時(shí),獲取該 Applicaiton類對(duì)象 & 調(diào)用exitApp()
private Carson_BaseApplicaiton app;
app = (Carson_BaseApplicaiton)getApplication();
app.exitApp();
優(yōu)點(diǎn):
缺點(diǎn): 兼顧單 / 多任務(wù)棧 & 多啟動(dòng)模式的情況
缺點(diǎn): 需要 Activity 經(jīng)歷正常的生命周期,即創(chuàng)建時(shí)調(diào)用onCreate(),結(jié)束時(shí)調(diào)用onDestroy()
方法六,使用RxBus,在每一個(gè)Activity里面訂閱,退出發(fā)送事件請(qǐng)求.
優(yōu)點(diǎn): 使用簡單
缺點(diǎn): 實(shí)現(xiàn)復(fù)雜:RxBus 本身的實(shí)現(xiàn)難度 & 需要在每個(gè)Activity注冊(cè)和取消訂閱 RxBus 使用
上述都只是完成了第一步,下面看如何結(jié)束進(jìn)程
// 方式1:android.os.Process.killProcess()
android.os.Process.killProcess(android.os.Process.myPid()) ;
// 方式2:System.exit()
// System.exit() = Java中結(jié)束進(jìn)程的方法:關(guān)閉當(dāng)前JVM虛擬機(jī)
System.exit(0);
// System.exit(0)和System.exit(1)的區(qū)別
// 1. System.exit(0):正常退出;
// 2. System.exit(1):非正常退出,通常這種退出方式應(yīng)該放在catch塊中。
Android中的ActivityManager時(shí)刻監(jiān)聽著進(jìn)程*。一旦發(fā)現(xiàn)進(jìn)程被非正常結(jié)束,它將會(huì)試圖去重啟這個(gè)進(jìn)程。
本文參考鏈接
https://mp.weixin.qq.com/s?__biz=MzI3MTEzMDI2MA==&mid=2654089109&idx=1&sn=1d979c74c8330e9e239efc42fb788719&chksm=f100046ec6778d78115b33fb439baf7f12ede9d08dc1e21d48d53bfaf20c39ef03ad58fea7d6&mpshare=1&scene=23&srcid=1117zY9fc7ObIdtaH41oMVxL#rd