http://blog.csdn.net/vipzjyno1/article/details/25423543
前言
由于一個同學問到我如何按照一個流程走好之后回到首頁,我以前看到過4個解決方案,后來發現有做個記錄和總結的必要,就寫了這篇博文。(之前看小強也寫過一篇,這里通過自身的分析完整的總結一下以下6種方案,并加上一個DEMO便于大家了解大體流程)
?
在android的用戶交互中,按鈕觸發的意圖(Intent)跳轉會為你重新打開新的一個界面活動(Activity),對于之前的界面根據需求進行摧毀(Finish())或則保留。
?
如果一個交互流程中,是從A開始,按照A - B - C - D - A這樣的順序進行的話,那么B,C,D這3個活動界面會根據你D中最后的操作來進行保留或是摧毀,例如
?
(1)注冊流程中,在A界面點擊注冊,通過B,C,D界面完成注冊后,B,C,D就隨之摧毀,而如果D中注冊不成功沒跳轉會A的話,那么B,C,D就不能摧毀,之前所填的內容也必須保留。
?
(2)客戶端交互中,返回首頁按鈕,由于在頻繁的點擊打開過多的界面(如微信查看朋友圈),返回首頁就必須一個一個back回去,所有有的客戶端為了優化用戶體驗,便會加入一個按鈕返回首頁(之前打開的全部關閉)。
?
以上幾個例子都涉及到了 ? --- ??如何安全退出多個ACTIVITY? ? 這個問題。
?
其實,這個問題的解決方案有好多種,并且各有各的優缺點,下面就羅列出多個方案以及各個方案的優缺點所在,以便用戶根據需求選擇。
?
知識結構
?
首先,通過大致的思維導圖羅列出了以下幾個知識點,來幫助你去分析學習:
?
1.Activity的啟動模式? ? ? ? ? ? ? ? ? ? ? ??
2.intent: ?Flags屬性,以及其顯、隱式 ? ?? ??
3.Application :?全局的使用
4.Activity: ?onActivityResult(int requestCode, int resultCode, Intent data)方法
5.棧的概念:Last-In/First-Out(LIFO) ? --- ?后進先出的原則?
6.BroadcastReceiver?廣播
7.棧的引申的知識點:(1)ArrayList和LinkedList的區別 ?(2)android 棧和隊列
?
以上的 (1)Activity的啟動模式 ?(2)intent: ?Flags屬性 ?(3)棧的概念 ? ? ? ??
我通過一篇文章寫明了他們3者的聯系可以點擊以下鏈接查看
Activity啟動模式 及 Intent Flags 與 棧 的關聯分析
?
?
具體方案
方案1
方法:采用FLAG_ACTIVITY_CLEAR_TOP退出整個程序(多activity)
思路:通過Intent的Flags來控制堆棧去解決
android中,每打開一個Activity,便會在棧中加入一個Activity,當該Activity被摧毀后,棧中便移除了它,并且棧中的Activity是按照開打的先后順序依次排排列的。
Android的窗口類提供了歷史棧,我們可以通過stack的原理來巧妙的實現,這里我們在A窗口打開B窗口時在Intent中直接加入標 志 Intent.FLAG_ACTIVITY_CLEAR_TOP,這樣開啟B時將會清除該進程空間的所有Activity。
代碼:
在注冊流程最后的FourthStep.class中,點擊完成注冊點擊事件
?
[java]?view plaincopy
btn_finish.setOnClickListener(new?OnClickListener()?{????????@Override??????public?void?onClick(View?v)?{??????????????????Intent?intent?=?new?Intent(INTENT_METHOD_FIRST_SINGUP);??????????intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);??????????startActivity(intent);??????}??});?? 其中的?INTENT_METHOD_FIRST_SINGUP 是登錄界面的Intent隱式Action。
?
優缺點:
優:使用對棧的巧妙利用,不會贊成內存無故占用等問題,個人認為這個方法是首選。
?
?
方案2
方法:通過堆棧管理器去管理
思路:通過堆棧管理器,對Stack進的存儲Activity進行操作(推入,推出,彈出)
代碼:
?
[java]?view plaincopy
public?class?StackManager?{??????????private?static?Stack?mActivityStack;??????private?static?StackManager?mInstance;????????????public?static?StackManager?getStackManager()?{??????????if?(mInstance?==?null)?{??????????????mInstance?=?new?StackManager();??????????}??????????return?mInstance;??????}????????????public?void?popActivity(Activity?activity)?{??????????if?(activity?!=?null)?{??????????????activity.finish();??????????????mActivityStack.remove(activity);??????????????activity?=?null;??????????}??????}????????????public?Activity?currentActivity()?{??????????????????if(mActivityStack?==?null?||?mActivityStack.size()?==0){??????????????return?null;??????????}??????????Activity?activity?=?(Activity)?mActivityStack.lastElement();??????????return?activity;??????}????????????public?void?pushActivity(Activity?activity)?{??????????if?(mActivityStack?==?null)?{??????????????mActivityStack?=?new?Stack();??????????}??????????mActivityStack.add(activity);??????}????????????public?void?popTopActivitys(Class?clsss)?{??????????while?(true)?{??????????????Activity?activity?=?currentActivity();??????????????if?(activity?==?null)?{??????????????????break;??????????????}??????????????if?(activity.getClass().equals(clsss))?{??????????????????break;??????????????}??????????????popActivity(activity);??????????}??????}????????????????public?void?popAllActivitys()?{??????????while?(true)?{??????????????Activity?activity?=?currentActivity();??????????????if?(activity?==?null)?{??????????????????break;??????????????}??????????????popActivity(activity);??????????}??????}??}?? 之后在注冊流程中的對應步驟的Activity的onCreate()中把當前Activity推入棧列表,完成注冊流程后,彈出棧列表中流程所涉及的Activity。
優缺點:
?
缺:如果處理不當,容易造成不在當前界面的Activity被全局引用而摧毀不掉,內存得不到釋放,從而無故占用不必要的內存。
?
方案3:
方法:全局記錄打開的Activity或通過一個自定義的類去管理打開的Activity
思路:通過在Application中用一個列表來記錄當前所打開的Activity,根據需求去遍歷finish()。
描述:和方案2有點類似。
代碼:
?
[java]?view plaincopy
public?class?AppApplication?extends?Application?{??????private?static?AppApplication?mAppApplication;??????????public?ArrayList<Activity>?activityList;????????@Override??????public?void?onCreate()?{??????????????????super.onCreate();??????????mAppApplication?=?this;??????}????????????public?static?AppApplication?getApp()?{??????????if?(mAppApplication?==?null)?{??????????????mAppApplication?=?new?AppApplication();??????????}??????????return?mAppApplication;??????}????????????public?void?addActivity(Activity?acitivity)?{??????????if(activityList?==?null){??????????????activityList?=?new?ArrayList<Activity>();??????????}??????????activityList.add(acitivity);??????}????????????????public?void?clearActivity(){??????????activityList.clear();??????}????????????public?void?exit()?{??????????for?(Activity?activity?:?activityList)?{??????????????activity.finish();??????????}??????????clearActivity();????????System.exit(0);??????}?? 使用流程和方法2類似。
?
優缺點:
缺:如果處理不當,容易造成不在當前界面的Activity被全局引用而摧毀不掉,內存得不到釋放,從而無故占用不必要的內存。
?
方案4
方法:使用廣播機制解決
思路:通過Activity創建的時候,設置監聽廣播,在注冊流程最后步完成注冊時候,發送廣播進行遍歷finish().
描述:這里我把這些廣播的初始化都寫在了基類BaseActivity里面,便于維護。
代碼:
[java]?view plaincopy
public?void?initFinishReceiver()?{??????IntentFilter?filter?=?new?IntentFilter();??????filter.addAction(INIENT_FINISH);??????registerReceiver(mFinishReceiver,?filter);??}????public?BroadcastReceiver?mFinishReceiver?=?new?BroadcastReceiver()?{????????@Override??????public?void?onReceive(Context?context,?Intent?intent)?{??????????if?(INIENT_FINISH.equals(intent.getAction()))?{??????????????finish();??????????}??????}??};?? 在流程中的每步Activity中,初始化廣播,之后在點擊完成注冊時候,發送廣播
[java]?view plaincopy
btn_finish.setOnClickListener(new?OnClickListener()?{????????@Override??????public?void?onClick(View?v)?{??????????????????getApplicationContext().sendBroadcast(new?Intent(INIENT_FINISH));??????}??});?? 優缺點:
缺:開啟過多的廣播監聽,覺得會浪費資源。
?
方案5:
方法:通過Activity跳轉中傳遞requestCode的之后根據onActivityResult(int requestCode, int resultCode, Intent data)中返回的resultCode遍歷關閉Activity
思路:使用startActivityForResult(intent, requestCode)方法跳轉,并且通過
描述:這里我把這些廣播的初始化都寫在了基類BaseActivity里面便于查看。
代碼:
?
[java]?view plaincopy
????public?final?static?int?FINISH_REQUESTCODE?=?1;??????????public?final?static?int?FINISH_RESULTCODE?=?1;??????????@Override??????protected?void?onActivityResult(int?requestCode,?int?resultCode,?Intent?data)?{??????????????????if(requestCode?==?FINISH_REQUESTCODE?){??????????????if(resultCode?==?FINISH_RESULTCODE){??????????????????setResult(FINISH_RESULTCODE);??????????????????finish();??????????????}??????????}??????????super.onActivityResult(requestCode,?resultCode,?data);??????}?? 之后在流程的Activity中調用帶請求碼的Intent跳轉意圖。
?
?
[java]?view plaincopy
startActivityForResult(new?Intent(getApplicationContext(),?SecondStep.class),FINISH_REQUESTCODE);?? 在最后完成注冊流程的時候通過以下方式返回:
[java]?view plaincopy
btn_finish.setOnClickListener(new?OnClickListener()?{????????@Override??????public?void?onClick(View?v)?{??????????????????setResult(FINISH_RESULTCODE);??????????finish();??????}??});?? ?
優缺點:
方案6(不推薦)
方法:方法有人說可以使用拋出異常來退出,可是這樣會影響到用戶體驗,所以不推薦
?
?
總結
以上便是我從注冊流程分析如何安全退出多個ACTIVITY 的匯總總結,綜上所述,博主覺得方案1是最可行的方法,如有什么錯誤之處,望大家提出,馬上改正。
?
?
源碼DEMO
?
最后附上源碼:下載地址? ?
?
(以上方式中都已經講到了對應的方法和代碼,源碼可以更好的幫助你去體驗下這幾種方式的使用流程)
轉載于:https://www.cnblogs.com/niray/p/3857270.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。