首页 > 其他分享 >从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)

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

时间:2023-05-16 10:02:32浏览次数:40  
标签:DEMO 流程 Activity Intent void activity new public


前言



 



由于一个同学问到我如何按照一个流程走好之后回到首页,我以前看到过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中,点击完成注册点击事件

 


    1. btn_finish.setOnClickListener(new OnClickListener() {  
    2.   
    3. @Override  
    4. public void onClick(View v) {  
    5. // TODO Auto-generated method stub  
    6. new Intent(INTENT_METHOD_FIRST_SINGUP);  
    7.         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  
    8.         startActivity(intent);  
    9.     }  
    10. });



    其中的 INTENT_METHOD_FIRST_SINGUP 是登录界面的Intent隐式Action。

     

    优缺点:

    优:使用对栈的巧妙利用,不会赞成内存无故占用等问题,个人认为这个方法是首选。

     

     

    方案2

    方法:通过堆栈管理器去管理

    思路:通过堆栈管理器,对Stack进的存储Activity进行操作(推入,推出,弹出)

    代码:

     


    1. public class StackManager {  
    2. /**
    3.      * Stack 中对应的Activity列表  (也可以写做 Stack<Activity>)
    4.      */  
    5. private static Stack mActivityStack;  
    6. private static StackManager mInstance;  
    7.   
    8. /**
    9.      * @描述 获取栈管理工具
    10.      * @return ActivityManager
    11.      */  
    12. public static StackManager getStackManager() {  
    13. if (mInstance == null) {  
    14. new StackManager();  
    15.         }  
    16. return mInstance;  
    17.     }  
    18.   
    19. /**
    20.      * 推出栈顶Activity
    21.      */  
    22. public void popActivity(Activity activity) {  
    23. if (activity != null) {  
    24.             activity.finish();  
    25.             mActivityStack.remove(activity);  
    26. null;  
    27.         }  
    28.     }  
    29.   
    30. /**
    31.      * 获得当前栈顶Activity
    32.      */  
    33. public Activity currentActivity() {  
    34. //lastElement()获取最后个子元素,这里是栈顶的Activity  
    35. if(mActivityStack == null || mActivityStack.size() ==0){  
    36. return null;  
    37.         }  
    38.         Activity activity = (Activity) mActivityStack.lastElement();  
    39. return activity;  
    40.     }  
    41.   
    42. /**
    43.      * 将当前Activity推入栈中
    44.      */  
    45. public void pushActivity(Activity activity) {  
    46. if (mActivityStack == null) {  
    47. new Stack();  
    48.         }  
    49.         mActivityStack.add(activity);  
    50.     }  
    51.   
    52. /**
    53.      * 弹出指定的clsss所在栈顶部的中所有Activity
    54.      * @clsss : 指定的类 
    55.      */  
    56. public void popTopActivitys(Class clsss) {  
    57. while (true) {  
    58.             Activity activity = currentActivity();  
    59. if (activity == null) {  
    60. break;  
    61.             }  
    62. if (activity.getClass().equals(clsss)) {  
    63. break;  
    64.             }  
    65.             popActivity(activity);  
    66.         }  
    67.     }  
    68.       
    69. /**
    70.      * 弹出栈中所有Activity
    71.      */  
    72. public void popAllActivitys() {  
    73. while (true) {  
    74.             Activity activity = currentActivity();  
    75. if (activity == null) {  
    76. break;  
    77.             }  
    78.             popActivity(activity);  
    79.         }  
    80.     }  
    81. }



    之后在注册流程中的对应步骤的Activity的onCreate()中把当前Activity推入栈列表,完成注册流程后,弹出栈列表中流程所涉及的Activity。
    优缺点:

     

    缺:如果处理不当,容易造成不在当前界面的Activity被全局引用而摧毁不掉,内存得不到释放,从而无故占用不必要的内存。

     

    方案3:

    方法:全局记录打开的Activity或通过一个自定义的类去管理打开的Activity

    思路:通过在Application中用一个列表来记录当前所打开的Activity,根据需求去遍历finish()。

    描述:和方案2有点类似。

    代码:

     

    1. public class AppApplication extends Application {  
    2. private static AppApplication mAppApplication;  
    3. /** 当前打开的activity列表 */  
    4. public ArrayList<Activity> activityList;  
    5.   
    6. @Override  
    7. public void onCreate() {  
    8. // TODO Auto-generated method stub  
    9. super.onCreate();  
    10. this;  
    11.     }  
    12.   
    13. /** 获取Application */  
    14. public static AppApplication getApp() {  
    15. if (mAppApplication == null) {  
    16. new AppApplication();  
    17.         }  
    18. return mAppApplication;  
    19.     }  
    20.   
    21. /** 添加当前Activity 到列表中 */  
    22. public void addActivity(Activity acitivity) {  
    23. if(activityList == null){  
    24. new ArrayList<Activity>();  
    25.         }  
    26.         activityList.add(acitivity);  
    27.     }  
    28.       
    29. /** 清空列表,取消引用*/  
    30. public void clearActivity(){  
    31.         activityList.clear();  
    32.     }  
    33.   
    34. /** 遍历退出所有Activity */  
    35. public void exit() {  
    36. for (Activity activity : activityList) {  
    37.             activity.finish();  
    38.         }  
    39. //千万记得清空取消引用。  
    40. 0);  
    41.     }



    使用流程和方法2类似。

     

    优缺点:

    缺:如果处理不当,容易造成不在当前界面的Activity被全局引用而摧毁不掉,内存得不到释放,从而无故占用不必要的内存。

     

    方案4

    方法:使用广播机制解决

    思路:通过Activity创建的时候,设置监听广播,在注册流程最后步完成注册时候,发送广播进行遍历finish().

    描述:这里我把这些广播的初始化都写在了基类BaseActivity里面,便于维护。

    代码:




      1. /**
      2.  * 初始化退出广播
      3.  */  
      4. public void initFinishReceiver() {  
      5. new IntentFilter();  
      6.     filter.addAction(INIENT_FINISH);  
      7.     registerReceiver(mFinishReceiver, filter);  
      8. }  
      9.   
      10. /**
      11.  * 监听是否退出的广播
      12.  */  
      13. public BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {  
      14.   
      15. @Override  
      16. public void onReceive(Context context, Intent intent) {  
      17. if (INIENT_FINISH.equals(intent.getAction())) {  
      18.             finish();  
      19.         }  
      20.     }  
      21. };



      在流程中的每步Activity中,初始化广播,之后在点击完成注册时候,发送广播


      1. btn_finish.setOnClickListener(new OnClickListener() {  
      2.   
      3. @Override  
      4. public void onClick(View v) {  
      5. // TODO Auto-generated method stub  
      6. new Intent(INIENT_FINISH));  
      7.     }  
      8. });


      优缺点:

      缺:开启过多的广播监听,觉得会浪费资源。

       

      方案5:

      方法:通过Activity跳转中传递requestCode的之后根据onActivityResult(int requestCode, int resultCode, Intent data)中返回的resultCode遍历关闭Activity

      思路:使用startActivityForResult(intent, requestCode)方法跳转,并且通过

      描述:这里我把这些广播的初始化都写在了基类BaseActivity里面便于查看。

      代码:

       



      1. /** 关闭时候的requestCode请求码 */  
      2. public final static int FINISH_REQUESTCODE = 1;  
      3. /** 关闭时候的resultCode请求码 */  
      4. public final static int FINISH_RESULTCODE = 1;  
      5. /**
      6.      * 方法5通过回调关闭的时候用到
      7.      */  
      8. @Override  
      9. protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
      10. // TODO Auto-generated method stub  
      11. if(requestCode == FINISH_REQUESTCODE ){  
      12. if(resultCode == FINISH_RESULTCODE){  
      13.                 setResult(FINISH_RESULTCODE);  
      14.                 finish();  
      15.             }  
      16.         }  
      17. super.onActivityResult(requestCode, resultCode, data);  
      18.     }



      之后在流程的Activity中调用带请求码的Intent跳转意图。

       

       



      1. startActivityForResult(new Intent(getApplicationContext(), SecondStep.class),FINISH_REQUESTCODE);



      在最后完成注册流程的时候通过以下方式返回:

      1. btn_finish.setOnClickListener(new OnClickListener() {  
      2.   
      3. @Override  
      4. public void onClick(View v) {  
      5. // TODO Auto-generated method stub  
      6.         setResult(FINISH_RESULTCODE);  
      7.         finish();  
      8.     }  
      9. });


       

      优缺点:

      方案6(不推荐)

      方法:方法有人说可以使用抛出异常来退出,可是这样会影响到用户体验,所以不推荐

       

       

      总结

      以上便是我从注册流程分析如何安全退出多个ACTIVITY 的汇总总结,综上所述,博主觉得方案1是最可行的方法,如有什么错误之处,望大家提出,马上改正。

       

       

      源码DEMO



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



       

      最后附上源码:下载地址   

       

      (以上方式中都已经讲到了对应的方法和代码,源码可以更好的帮助你去体验下这几种方式的使用流程)

      标签:DEMO,流程,Activity,Intent,void,activity,new,public
      From: https://blog.51cto.com/u_16112859/6282448

      相关文章

      • 网络安全等级保护测评工作流程
        一、测评准备活动阶段首先,被测评单位在选定测评机构后,双方需要先签订《测评服务合同》,合同中对项目范围(系统数量)、项目内容(差距测评?验收测评?协助整改?)、项目周期(什么时间进场?项目计划做多长时间?)、项目实施方案(测评工作的步骤)、项目人员(项目实施团队人员)、项目验收标准、付款方式、......
      • uniapp测试环境下安卓端和iOS端打包流程
        方法步骤:1.选中你要打包的项目 2.打包对应的应用系统,以下分为安卓端和iOS端 一、安卓端:安卓证书申请流程如下: 参考地址:https://ask.dcloud.net.cn/article/35777二、iOS端: iOS端证书申请流程如下:1.描述: 2.准备环境3.登录iOSDevCenter打开网站 iOSDe......
      • 如何安全退出已调用多个Activity的Application
        如何安全退出已调用多个Activity的Application?思路如下:建一个工具类,在里面管理activity的添加,移除和退出app的操作;第一步,创建一个名字为ActivityManage的工具类,里面有添加activity,移除activity和退出activity的方法,代码如下:publicclassActivityManage{publ......
      • 线程池的执行流程
        当核心线程已满的情况下,首先就把请求提交给阻塞队列,只有当阻塞队列也满的情况下,才会创新非核心线程处理   ......
      • w1r3s靶场流程
        w1r3s靶场实验环境w1r3s靶场:192.168.134.139kali:192.168.134.135信息收集利用nmap进行主机发现nmap-sn192.168.134.0/24利用nmap扫描全部的端口nmap--min-rate10000-p-192.168.134.139#–min-rate,用来指定Nmap每秒钟发送的数据包数量最小是10000#-p-,“-p"参数......
      • 第139篇:微信小程序的登录流程
        好家伙,补补补 顶不住了,跑不掉了,这部分的知识还是要补上 来看看微信小程序登录的完整流程 最左边的一列就是前端负责的部分了几个关键的参数:code:一个用户登录凭证,就是一个临时的tokenAppid:appid是微信账号的唯一标识,这个是固定不变的;如果了解微信公众号开发的就需要......
      • LabVIEW测试测量项目Demo数据库操作演示项目结构搭建源码
        LabVIEW测试测量项目Demo数据库操作演示项目结构搭建源码ID:7698671837695583......
      • 按照敏捷需求分析的流程
        1.用户愿景用户愿景就是满足什么样的用户在什么条件下的什么需求。如,购物网站是为了满足购物需求,社交软件是为了满足社交的需要。购物网站的社交需求,社交产品的购物需求一定是与产品的核心服务不统一的。在做需求分析时一定要多问一问是不是符合产品定位?好需求但不一定是适合的需......
      • LabVIEW 面向对象编程(oop)-简单工厂模式程序Demo,基于Modbus的RS485通讯,程序Demo已经
        LabVIEW面向对象编程(oop)-简单工厂模式程序Demo,基于Modbus的RS485通讯,程序Demo已经过初步验证测试效果良好,整体操作过程已录制视频(视频时长40分钟),手把手进行讲解简单工厂模式的注意点和编写步骤,手把手教你创建一个简单工厂模式。ID:7156622766004941......
      • 智能硬件项目全流程
         编辑智能硬件项目全流程阶段流程节点细分活动活动说明核心关注点市场调研市场调研收集市场需求1.目标客户群体的具体需求与痛点是什么?他们最需要什么产品与服务? 2.谁是我们的竞争对手?他们的产品优缺点及定价策略是什么?现有市场竞争态势如何?我们有什么竞争优势? 3.潜......