#android--自定义栈管理Activity,实现一次退出所有的Activity

来源:互联网 发布:软件可靠性指标 编辑:程序博客网 时间:2024/05/16 06:54

What–需求分析

今天写项目的时候遇到个问题,因为是加载的webview,点击响应时先会判断是否已经登录超时,如果是,那么结束掉之前的所有页面,回到登录页重新登录。那么问题就来了,之前只做过结束掉当前Activity,那么如何结束之前的所有栈中的Activity呢。看下面的分析

How–如何去做

首先简单说一下堆栈的概念。如图所示,也就是先进后出的原则

add和remove时Activity栈示意图

所以我们可以定义一个栈(Stack)去管理Activity,当创建Activity的时候就往栈添加这个Activity,当Activity销毁时就把这个Activity从这个栈里移除。想要finish掉所有Activity,只需要遍历stack,然后Finish掉每个Activity即可。

Code – 代码展示

首先来看一下管理Activity的关键类

因为用来管理Activity的类只能有一个实例,所以就用到了单例模式。
在构造方法里创建了一个stack去管理Activity,Activity入栈是调用push方法,Activity出栈时调用pop方法。当结束掉所有Activity时遍历stack,然后finish。哦,记得一定要判空处理。

public class ActivityStackManager {    private static ActivityStackManager mInstance;    private static Stack<Activity> mActivityStack;    public static ActivityStackManager getInstance() {        if (null == mInstance) {            mInstance = new ActivityStackManager();        }        return mInstance;    }    private ActivityStackManager() {        mActivityStack = new Stack<Activity>();    }    // 入栈    public void addActivity(Activity activity) {        mActivityStack.push(activity);        Log.d("_addActivity","addActivity=="+activity.getLocalClassName());    }    // 出栈    public void removeActivity(Activity activity) {        mActivityStack.remove(activity);        Log.d("removeActivity","removeActivity=="+activity.getLocalClassName());    }    //  彻底退出    public void finishAllActivity() {        Activity activity;        while (!mActivityStack.empty()) {            activity = mActivityStack.pop();            if (activity != null) {                activity.finish();                Log.d("finishAllActivity","finishActivity=="+activity.getLocalClassName());            }        }    }    // 结束指定类名的Activity    public void finishActivity(Class<?> cls) {        for (Activity activity : mActivityStack) {            if (activity.getClass().equals(cls)) {                finishActivity(activity);            }        }    }    // 查找栈中是否存在指定的activity    public boolean checkActivity(Class<?> cls) {        for (Activity activity : mActivityStack) {            if (activity.getClass().equals(cls)) {                return true;            }        }        return false;    }    // 结束指定的Activity    public void finishActivity(Activity activity) {        if (activity != null) {            mActivityStack.remove(activity);            activity.finish();            activity = null;        }    }    // finish指定的activity之上所有的activity    public boolean finishToActivity(Class<? extends Activity> actCls, boolean isIncludeSelf) {        List<Activity> buf = new ArrayList<Activity>();        int size = mActivityStack.size();        Activity activity = null;        for (int i = size - 1; i >= 0; i--) {            activity = mActivityStack.get(i);            if (activity.getClass().isAssignableFrom(actCls)) {                for (Activity a : buf) {                    a.finish();                }                return true;            } else if (i == size - 1 && isIncludeSelf) {                buf.add(activity);            } else if (i != size - 1) {                buf.add(activity);            }        }        return false;    }

再来看一下如何在Activity中调用

因为相当于是一个全局的管理,所以把入栈出栈放在基类里面比较方便。看一下BaseAtivity里的代码

public abstract  class BaseActivity extends Activity{    @Override    protected void onCreate(final Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ActivityStackManager.getInstance().addActivity(this);    }    @Override    protected void onDestroy() {        ActivityStackManager.getInstance().removeActivity(this);        super.onDestroy();    }}

ok,是不是很简单。在oncreate方法里把当前Activity压入栈中,然后在ondestory方法里将当前Activity从栈中弹出。

然后就是具体的 Activity去继承BaseActvity。好了,关键代码已完成。来看一个测试。点击MainActivity中的TextView 跳转到FirstActivity,点击FirstAtivity里的TextView跳转到SecondActivity……以此类推,当点击FourthActivity时结束掉所有的Activity并重新打开MainActivity。
这里写图片描述

具体代码:
MainActivity:

public class MainActivity extends BaseActivity {    TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv= (TextView) findViewById(R.id.tv);        tv.setText("MainActivity");        tv.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(final View v) {                Log.d("_onclick","==MainActivity");                startActivity(new Intent(MainActivity.this,FirstActivity.class));            }        });    }}

FourthActivity:

public class FourthActivity extends BaseActivity{    TextView tv;    @Override    protected void onCreate(final Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv= (TextView) findViewById(R.id.tv);        tv.setText("FourthActivity");        tv.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(final View v) {                Log.d("_onclick","==FourthActivity");                startActivity(new Intent(FourthActivity.this,MainActivity.class));                ActivityStackManager.getInstance().finishAllActivity();            }        });    }

对了,在管理Activity的那个类add和remove方法中输出log。
看一下输出日志:
这里写图片描述

可以看到,每次创建时就会往stack里添加Activity,当结束所有Activity时就会遍历stack,先走finish方法,触发ondestory方法,然后把Activity从Stack中移除。

这里有个疑问,就是看输出日志显示Finish掉Activity的顺序是Fourth、Third、Second、First 很符合逻辑,但是从stack中移除时的顺序是Third、Second、First、Fourth。按逻辑来说,finish的时候会走ondestory方法然后走remove方法的,所以不明白这里为什么Fourth是最后一个被移除的。希望有人指点迷津,不胜感激。

PS

ActivityStackManager 这个类原文找不到了,若有侵权,请指正。

0 0
原创粉丝点击