Android實現點擊兩次退出APP
這兩天在做一個項目碰到這么個問題,需要主界面點擊兩次直接退出整個APP而不是返回上一個界面,查找了網上的資料,整合和修改了一下寫了這篇博客。
這里我主要以我的項目為例,實現了登錄界面,注冊界面,在登錄界面登錄成功則跳轉到主界面上,而主界面點擊退出回到了登錄界面,這顯然是不合理的,需要主界面點擊返回按鈕退出整個APP,同時為了防止誤觸,還應該實現點擊一次提醒用戶,點擊兩次退出整個APP,市面上的大多APP也是這么干的,這樣的用戶體驗也會更好。
話不多說,我們來看代碼
1、實現活動的集合類
這里主要實現點擊返回按鈕退出程序的功能,也會是隨時隨地退出程序。
新建一個ActivityCollector類作為活動管理器,代碼如下:
import android.app.Activity; import java.util.ArrayList; import java.util.List; //提供一個專門的集合類對所有的活動進行管理 //方便隨時退出程序
public class ActivityCollector { public static List<Activity> sActivities=new ArrayList<>(); public static void addActivity(Activity activity){ sActivities.add(activity); } public static void removeActivity(Activity activity){ sActivities.remove(activity); } public static void finishAll(){ for(Activity activity:sActivities){ if(!activity.isFinishing()){ activity.finish(); } } sActivities.clear(); } }
在活動管理器中,我們通過一個Activity的List來暫存活動,addActivity()方法向其中添加活動,removeActivity()方法移除活動,最后提供了一個finishAll()方法用於將List中的活動全部銷毀。
接下來修改主界面之前的活動,這里我主要是在登錄界面和注冊界面中添加了如下代碼:
public class XXXXActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityCollector.addActivity(this); } @Override protected void onDestroy(){ super.onDestroy(); ActivityCollector.removeActivity(this); }
接着在啟動主界面的 Intent 后需要添加下面這行代碼:
ActivityCollector.finishAll();
這樣在主界面上點擊返回按鈕會直接退出整個APP。
其實上面這些代碼的主要作用就是讓新活動入棧的之前清空活動棧,這樣當新活動入棧后活動棧內只有一個活動,點擊返回按鈕當然就能直接退出程序。
接下來我們來實現點擊兩次退出APP
2、實現點擊兩次退出APP
網上實現的代碼主要是兩種方式:
(1)、利用Handler
(2)、利用系統秒數
這兩個方法的核心其實都是利用時間差,如果在限定的時間內點擊了兩次返回鍵就退出程序。
這里我忍不住想吐槽一下網上的代碼,很多人轉的都是同一份代碼,然而那份代碼有個錯誤不能正常運行,只需要改動一下就可以使用,希望大家在轉博客的時候也能先運行一下,能運行通過的再轉,別搞的搜到的都是錯誤的代碼。
這里給出兩種方法實現的代碼:
(1)、利用Handler
代碼如下
//定義一個變量,來標識是否退出
private static int isExit=0; //實現按兩次后退才退出
Handler handler=new Handler(){ @Override public void handleMessage(Message msg){ super.handleMessage(msg); isExit--; } }; @Override public boolean onKeyDown(int keyCode, KeyEvent event){ if(keyCode==KeyEvent.KEYCODE_BACK){ isExit++; exit(); return false; } return super.onKeyDown(keyCode,event); } private void exit(){ if(isExit<2){ Toast.makeText(getApplicationContext(),R.string.Exit,Toast.LENGTH_SHORT).show(); //利用handler延遲發送更改狀態信息
handler.sendEmptyMessageDelayed(0,2000); }else{ super.onBackPressed(); } }
這里我簡略介紹一下這個代碼。
首先定義一個整型變 isExit 量來記錄返回按鈕的點擊次數,默認為0。接下來創建一個Handler,用來處理發送過來的信息,這是 Android 提供的一套異步消息處理機制,在子線程中更新UI也會用到這一套機制,接觸過AsyncTask的人應該對於這個比較了解,AsyncTask實際上就是基於異步消息處理機制,只是Android幫我們做了很好的封裝而已。
重寫了父類的onKeyDown()方法,每點擊一次返回按鈕就會調用這個方法,給 isExit 的值增加1,調用 exit() 判斷是否要退出程序。第一次點擊時 isExit 的值增加1,其值為1,調用 exit() ,彈出提示框提醒用戶再點擊一次退出程序,並調用剛才創建的 handler 發送修改 isExit 為0,這里設置其延時2秒發送,如果2秒之內用戶再次點擊,又會給 isExit 的值增加1,這是調用 exit() 方法會直接調用 super.onBackPressed() 方法直接退出程序,顯然上面發送的消息也到不了 handler 里面,程序也就可以正常退出。如果2秒內用戶沒有再次點擊返回鍵,isExit的值再次置為0,用戶則需要再次點擊兩次返回鍵方能退出程序。
(2)、利用系統秒數
代碼如下:
private static final int TIME_EXIT=2000; private long mBackPressed; @Override public void onBackPressed(){ if(mBackPressed+TIME_EXIT>System.currentTimeMillis()){ super.onBackPressed(); return; }else{ Toast.makeText(this,"再點擊一次返回退出程序",Toast.LENGTH_SHORT).show(); mBackPressed=System.currentTimeMillis(); } }
這個方法比上面的原理還要簡單些,這里就不再贅述了。
這里我解釋一下為什么沒直接調用用 finsh() 或則是直接使用 System.exit(0),網上很多的代碼都是這樣做的。
在 Android 開發網的文檔上我們可以找到給 finish() 的介紹:
You can shut down an activity by calling its finish() method. You can also shut down a separate activity that you previously started by calling finishActivity(). Note: In most cases, you should not explicitly finish an activity using these methods. As discussed in the following section about the activity lifecycle, the Android system manages the life of an activity for you, so you do not need to finish your own activities. Calling these methods could adversely affect the expected user experience and should only be used when you absolutely do not want the user to return to this instance of the activity.
Android官方也並不建議我們使用這種方法,使用過的也應該知道使用這種方法直接退出的效果很差,並不像 Android 自帶應用退出時的動畫那么流暢,所以建議不使用這個方法。
至於System.exit(0),這個方法就更不建議了。
本文系原創,轉載還請注明出處。
本文主要參考了:
1、《Android 第一行代碼》第二版,郭霖著;
2、https://www.cnblogs.com/jojodru/p/5443303.html