日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)

發布時間:2025/4/16 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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)?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????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?{??
  • ????/**?
  • ?????*?Stack?中對應的Activity列表??(也可以寫做?Stack<Activity>)?
  • ?????*/??
  • ????private?static?Stack?mActivityStack;??
  • ????private?static?StackManager?mInstance;??
  • ??
  • ????/**?
  • ?????*?@描述?獲取棧管理工具?
  • ?????*?@return?ActivityManager?
  • ?????*/??
  • ????public?static?StackManager?getStackManager()?{??
  • ????????if?(mInstance?==?null)?{??
  • ????????????mInstance?=?new?StackManager();??
  • ????????}??
  • ????????return?mInstance;??
  • ????}??
  • ??
  • ????/**?
  • ?????*?推出棧頂Activity?
  • ?????*/??
  • ????public?void?popActivity(Activity?activity)?{??
  • ????????if?(activity?!=?null)?{??
  • ????????????activity.finish();??
  • ????????????mActivityStack.remove(activity);??
  • ????????????activity?=?null;??
  • ????????}??
  • ????}??
  • ??
  • ????/**?
  • ?????*?獲得當前棧頂Activity?
  • ?????*/??
  • ????public?Activity?currentActivity()?{??
  • ????????//lastElement()獲取最后個子元素,這里是棧頂的Activity??
  • ????????if(mActivityStack?==?null?||?mActivityStack.size()?==0){??
  • ????????????return?null;??
  • ????????}??
  • ????????Activity?activity?=?(Activity)?mActivityStack.lastElement();??
  • ????????return?activity;??
  • ????}??
  • ??
  • ????/**?
  • ?????*?將當前Activity推入棧中?
  • ?????*/??
  • ????public?void?pushActivity(Activity?activity)?{??
  • ????????if?(mActivityStack?==?null)?{??
  • ????????????mActivityStack?=?new?Stack();??
  • ????????}??
  • ????????mActivityStack.add(activity);??
  • ????}??
  • ??
  • ????/**?
  • ?????*?彈出指定的clsss所在棧頂部的中所有Activity?
  • ?????*?@clsss?:?指定的類??
  • ?????*/??
  • ????public?void?popTopActivitys(Class?clsss)?{??
  • ????????while?(true)?{??
  • ????????????Activity?activity?=?currentActivity();??
  • ????????????if?(activity?==?null)?{??
  • ????????????????break;??
  • ????????????}??
  • ????????????if?(activity.getClass().equals(clsss))?{??
  • ????????????????break;??
  • ????????????}??
  • ????????????popActivity(activity);??
  • ????????}??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?彈出棧中所有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;??
  • ????/**?當前打開的activity列表?*/??
  • ????public?ArrayList<Activity>?activityList;??
  • ??
  • ????@Override??
  • ????public?void?onCreate()?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????super.onCreate();??
  • ????????mAppApplication?=?this;??
  • ????}??
  • ??
  • ????/**?獲取Application?*/??
  • ????public?static?AppApplication?getApp()?{??
  • ????????if?(mAppApplication?==?null)?{??
  • ????????????mAppApplication?=?new?AppApplication();??
  • ????????}??
  • ????????return?mAppApplication;??
  • ????}??
  • ??
  • ????/**?添加當前Activity?到列表中?*/??
  • ????public?void?addActivity(Activity?acitivity)?{??
  • ????????if(activityList?==?null){??
  • ????????????activityList?=?new?ArrayList<Activity>();??
  • ????????}??
  • ????????activityList.add(acitivity);??
  • ????}??
  • ??????
  • ????/**?清空列表,取消引用*/??
  • ????public?void?clearActivity(){??
  • ????????activityList.clear();??
  • ????}??
  • ??
  • ????/**?遍歷退出所有Activity?*/??
  • ????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)?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????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
  • /**?關閉時候的requestCode請求碼?*/??
  • ????public?final?static?int?FINISH_REQUESTCODE?=?1;??
  • ????/**?關閉時候的resultCode請求碼?*/??
  • ????public?final?static?int?FINISH_RESULTCODE?=?1;??
  • ????/**?
  • ?????*?方法5通過回調關閉的時候用到?
  • ?????*/??
  • ????@Override??
  • ????protected?void?onActivityResult(int?requestCode,?int?resultCode,?Intent?data)?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????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)?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????setResult(FINISH_RESULTCODE);??
  • ????????finish();??
  • ????}??
  • });??
  • ?

    優缺點:

    方案6(不推薦)

    方法:方法有人說可以使用拋出異常來退出,可是這樣會影響到用戶體驗,所以不推薦

    ?

    ?

    總結

    以上便是我從注冊流程分析如何安全退出多個ACTIVITY 的匯總總結,綜上所述,博主覺得方案1是最可行的方法,如有什么錯誤之處,望大家提出,馬上改正。

    ?

    ?

    源碼DEMO

    ?

    最后附上源碼:下載地址? ?

    ?

    (以上方式中都已經講到了對應的方法和代碼,源碼可以更好的幫助你去體驗下這幾種方式的使用流程)

    轉載于:https://www.cnblogs.com/niray/p/3857270.html

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。