解决Android被系统回收,重打开崩溃等问题

流程再现:
假设第一个进栈的是FirstActivity,FirstActivity中打开SecondActivity,Second中用了First的静态变量list。如下:

public class FirstActivity extends BaseActivity {

    public static List<String> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.testxml);
        list = new ArrayList<>();
        startActivity(new Intent(this, SecondActivity.class));
    }

}
public class SecondActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.testxml);
        Log.e("~", FirstActivity.list.size() + "");

    }

}

到SecondActivity界面时,按下Home键回到主界面,同时用AndroidStudio杀掉进程。
这里写图片描述
再点开应用,崩溃,报NullPointException,原因是SecondActivity重新onCreate中引用的list为空。

这只是一个简单的例子,app中有很多类似的问题可能会发生,导致应用Crash。

Android的垃圾回收机制会回收掉static关键字占用的内存,我们可以从这一点出发,来制定我们的解决方案。简单分为以下3个步骤:
Step 1:做一个单例,记录App状态;

public class AppStatusManager {

    private static AppStatusManager mInstance = null;

    private int appStatus = AppStatusConstant.APP_FORCE_KILLED;

    private AppStatusManager() {

    }

    public static AppStatusManager getInstance() {
        if(mInstance==null) {
            synchronized (AppStatusManager.class) {
                if(mInstance==null)
                    mInstance = new AppStatusManager();
            }
        }
        return mInstance;
    }

    public void setAppStatus(int appStatus) {
        this.appStatus = appStatus;
    }

    public int getAppStatus() {
        return appStatus;
    }


    public static class AppStatusConstant {

        /**
         * App被回收,初始状态
         */
        public static final int APP_FORCE_KILLED = 0;

        /**
         * 正常运行
         */
        public static final int APP_NORMAL = 1;
    }
}

Step 2:所有Activity的父类BaseActivity.onCreate中调用如下方法;

private void checkAppStatus() {
    if(AppStatusManager.getInstance().getAppStatus()==AppStatusManager.AppStatusConstant.APP_FORCE_KILLED) {
        //该应用已被回收,执行相关操作(下面有详解)
    }
}

Step 3:应用栈底Activity.onCreate前把status改成运行状态;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     AppStatusManager.getInstance().setAppStatus(AppStatusManager.AppStatusConstant.APP_NORMAL);
     super.onCreate(savedInstanceState);

 }

OK,到这里基本就已经大功告成了。

但是!!已经进栈的Activity还是存在的,如果用户点返回键回到上一个Activity,重新onCreate,还是有可能Crash。我们需要关闭之前所有的Activity,然后走重启流程。

关闭所有Activity的方法大致有如下几种:

  1. 创建static Set< Activity>,每个Activity创建时动态添加。但是刚才已经讨论过了,static会被回收,行不通;
  2. 广播注册法,Activity.onCreate中注册广播,一旦检测到被回收,发送广播全部关掉。被回收,其实就相当于Broadcast被unregister,不展开讨论;
  3. 通过startActivityForResult启动Activity,每个Activity.onActivityResult中进行不同的处理(finish() | 其它操作)。这么做确实可行,但是有2个问题。一,如果上个Activity.onCreate中有startActivity(),那么会再次启动;二,每个Activity都被串起来了,代码太多、耦合性太强,不建议;

看到这些都不可行,是不是感觉要GG了,大清要亡我啊!!!但正所谓“飞流直下三千尺,柳暗花明又一村。”,我们先来看Intent.java一个变量。

    /**
     * If set in an Intent passed to {@link Context#startActivity Context.startActivity()},
     * this flag will cause any existing task that would be associated with the
     * activity to be cleared before the activity is started.  That is, the activity
     * becomes the new root of an otherwise empty task, and any old activities
     * are finished.  This can only be used in conjunction with {@link #FLAG_ACTIVITY_NEW_TASK}.
     */
    public static final int FLAG_ACTIVITY_CLEAR_TASK = 0X00008000;

这一大堆英文是什么鬼!!!但是作为一名优秀的程序员,要有提炼精华的能力。上面一大堆英文,可以简括概要为一句:

the activity becomes the new root of an otherwise empty task, and old activities are finished.

大致意思就是,我们的应用开了个新的栈玩,之前那个栈里的Activity都会被关掉。至此,水落石出,借用这点完善上面的BaseActivity.checkAppStatus():

private void checkAppStatus() {
    if(AppStatusManager.getInstance().getAppStatus()==AppStatusManager.AppStatusConstant.APP_FORCE_KILLED) {
        //应用启动入口SplashActivity,走重启流程
        Intent intent = new Intent(this, SplashActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        startActivity(intent);
    }
 }

大功告成,赶紧回去解决你的BUG吧。


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值