解决Android被系统回收,重打开崩溃等问题
来源:互联网 发布:linux系统当前版本 编辑:程序博客网 时间:2024/06/06 01:09
流程再现:
假设第一个进栈的是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的方法大致有如下几种:
- 创建static Set< Activity>,每个Activity创建时动态添加。但是刚才已经讨论过了,static会被回收,行不通;
- 广播注册法,Activity.onCreate中注册广播,一旦检测到被回收,发送广播全部关掉。被回收,其实就相当于Broadcast被unregister,不展开讨论;
- 通过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吧。
- 解决Android被系统回收,重打开崩溃等问题
- 如何处理android程序变为后台程序,系统回收资源,再次打开时,程序因为null指针等崩溃
- 如何处理android程序变为后台程序,系统回收资源,再次打开时,程序因为null指针等崩溃
- 解决Activity被系统回收问题
- 解决Activity被系统回收问题
- 解决Activity被系统回收问题
- 解决VC6.0打开文件崩溃问题
- 三星Note3 N900解决WIFI无法打开、打开缓慢、卡死、wifi密码重启不能保存等问题
- 解决小米miui系统调用系统裁剪图片功能camera.action.CROP后崩溃或重新打开app的问题
- 解决小米miui系统调用系统裁剪图片功能camera.action.CROP后崩溃或重新打开app的问题
- 解决visual c++6.0中打开文件崩溃问题
- 解决uploadify插件浏览器打开页面崩溃问题
- 解决uploadify插件浏览器打开页面崩溃问题
- mac版andriod studio 打开即崩溃问题的解决
- android 应用异常可以引起android系统崩溃重启
- Android 解决ViewPage轮播两张崩溃问题
- 解决Android图片剪切返回崩溃问题
- 电脑重启问题——系统崩溃
- 一、java版本与配置
- Jersey restful任何访问都404和接收json对象
- iOS学习笔记-027.UITableViewCell的基本用法
- NodeJS写日志_Log4js使用详解+常见艰难的解决
- 程序员面试金典——解题总结: 9.18高难度题 18.4编写一个方法,数出0到n(含)中数字2出现了几次
- 解决Android被系统回收,重打开崩溃等问题
- RTMP协议封包分析
- java设计模式(1)观察者模式
- MyBatis 多表联合查询及优化
- dfs序
- git的实际操作指令总结
- 在 Angularjs 中 ui-sref 和 $state.go 如何传递参数
- Mongodb的集合插入一个字段
- Hibernate @Cache注解