APP长期在后台,有可能导致activity被内存回收,这时候再次点开APP的时候,由于activity里面的数据被清空,控件也变成了null,导致空指针出现。
目前有两种解决思路:
1、使用onSaveInstanceState和onRestoreInstanceState来保存UI状态的,基本上就是在按home键或者其他情况的时候存储数据,然后再次点开APP的时候读取bundle的数据,这种网上太多了,我就不说具体怎么做,这里只说我关于这种思路的看法。
(1)这种保存数据的做法只能存储数据,解决像list空指针的问题,但是不能解决控件空指针的问题。
(2)然后实际上一个项目那么多个页面,而且activity和fragment保存数据的方法还不一样,不可能一个一个页面去存储和读取数据的,不太现实。
(3)网上说的baseactivity重写这2个方法,然后其他activity继承,也不过是存储了公共数据,比如token这些,但是实际上每个页面的数据差的很多,不能这么存的,实际意义很有限。
感兴趣的小伙伴可以看下该方法的具体实现
2.另一种是我目前使用的,基于内存回收activty,变量也被回收了,做法是在application写一个public static的int变量值,值为-1,然后在启动页的onCreate里面把值变成1,然后在baseactivity的onCreate里面监听这个值,如果是-1说明变量被回收了,这个时候就可以跳转到主页(启动模式一般为SingleTask,保证MainActivty在栈中只有一个并且在最底层),并把页面关了,如果之前有写管理activity的工具类,遍历一下关掉,可以在启动页做这个操作。
这里记录一下第二种思路的解决办法:
1、在applciation中声明变量flag,用于标志程序是否被杀掉
public class MyApplication extends Application {
public static int flag = -1;
......
}
2、在启动页(SplashActivity)中改变flag的值
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
MyApplication.flag = 1; //进入应用改变flag值,标识正常进入App
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
handler.sendEmptyMessageDelayed(0, 3000);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
};
}
3、新建BaseActivity(除SplashActivity外所有Activity都需要继承这个Activity),在这里判断是否需要重启程序
public abstract class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(MyApplication.flag == -1) { //flag为-1说明程序被杀掉
protectApp();
} else {
setContentView();
initializeView();
initializeData();
}
}
protected void protectApp() {
Intent intent = new Intent(this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//清空栈里MainActivity之上的所有activty
startActivity(intent);
finish();
}
protected abstract void initializeData();
protected abstract void initializeView();
protected abstract void setContentView();
}
4、MainActivity中复写protectApp()方法,直接跳转到启动页,重启activty,重新初始化application中的静态变量
@Override
protected void protectApp() {
startActivity(new Intent(this,SplashActivity.class));
finish();
}
如果想探究如何模拟app被内存杀死,可以查看这篇文章