1.问题是如何发生的,会在什么情况下发生此类问题?
当用户运用手机清理助手或后台回收我们的应用造成我们应用程序进程被杀死的时候就有可能出现这种空指针的问题,下面举个例子我们一起来看看这种情况是如何发生的。
如图所示我们新建一个程序Demo,程序中有三个Activity,分别为SplashActivity MainActivity InfoActivity,下面我们简称这三个Activity为A B C.这三个Activity也是模拟我们平时项目的进入流程,SplashActivity也就是我们的欢迎页面,当此Activity显示完后我们让它finish掉。MainActivity是我们的主页面,通常这个页面启动模式都是设置成SINGLETASK的,不明白为什么设置成这个模式的同学可以去百度一下Activity的启动模式,而InfoActivity则是我们的二级页面。
如上图我们自定义一个application类,大家都知道这个类是在整个程序启动时最先被加载的,同时我们在这个里边定义一个集合list。
看到这里我们可能会疑惑了,为什么要定义这么一个集合呢??
答:这个集合是为了方便我们模拟出空指针异常出现而准备的,当然这么写只是方便模拟,大家在日常开发中有可能会因为其他原因而出现此类问题。
接下来我们看看这个集合的初始化。如图:可以看到这个集合是在mainactivity中被初始化的时候new出来的,同时我们给赋一个值。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplication.list=new ArrayList<>();
MyApplication.list.add("我从MAINACTIVITY来");
Button button= (Button) findViewById(R.id.activity_main_btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,InfoActivity.class));
}
});
}
}
当我们点击按钮时跳到了InfoActivity中,再让我们看看InfoActivity中是如何处理的。
public class InfoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info);
TextView textView= (TextView) findViewById(R.id.text);
textView.setText(MyApplication.list.get(0));
}
}
很简单只是将控件赋值了。
好,让我们看看整个流程。
哈哈,很简单吧!!接下来让我们模拟一下异常的发生!我们将应用放到InfoActivity页面,同时摁下home键将程序放到后台,然后用android studio强制结束我们的进程,再点开应用我们一起来看看会发生什么。
当我们再点开应用的时候便会发现!咦!发生异常了!!
让我们来分析一下为什么会出现这种情况,显而易见是因为给textview赋值时集合为空而导致的,而我们的集合是在当MainActivity中new并赋值的。当我们的进程被强杀或者被回收的时候,Android系统虽然让你的进程没有了,但是此进程中Activity中栈的信息还是存在的,也就是说此时当你点开此应用的时候程序中的Activity栈还是存在着B→C这两个Activity的,只不过Activity中的数据都没有了,需要重新创建新的Activity数据,也就是重新走生命周期了,当我们的InfoActivity重新走到14行时,因为MainActivity中的数据没有初始化(只有当我们回退键退到MainActivity才会走生命周期),而这个集合是在MainActivity中被初始化的,所以这个集合肯定为空。这也就导致了空指针异