从界面跳转后被系统Kill来看Activity的方法调用

在xx手机上速配出现bug修复的任务,软件在xx手机上打开,跳过一个界面,就把上一个界面给Kill了,刚开始以为是xx手机修改了android系统,后来发现是手机太烂了,内存太低了,每次跳转都因内存不足把上个界面给Kill了,正好让我复习和实际运用一下Activity中的onSaveInstanceState方法和onRestoreInstanceState方法!

纸上得来终觉浅,绝知此事要躬行!以前在网上学习了onSaveInstanceState方法和onRestoreInstanceState方法,一直都很少机会体验它存在的场景,没有深刻的体会,这次让我再次感受到学习开发就是理论后要多实践,不管多难都要上手去做,才能更深刻的理解那些理论原理!

1、让程序出现被系统kill的场景,而且onSaveInstanceState方法和onRestoreInstanceState方法都调用!

A、运行你的程序,当程序打开时,按HOME键,这时系统会调用onSaveInstanceState方法,注意:这个方法的调用是系统决定的,不是软件或者其他什么因素,系统觉得有可能在某个时间因内存不足等因素而Kill掉你,所以给你个机会让你现在先利用这个方法保存下数据,所以调用onSaveInstanceState方法。

B、一般情况下,即使你在onSaveInstanceState保存了数据,在系统没Kill掉程序的情况下,你再回到刚关闭的界面,你也会感觉刚才调用onSaveInstanceState方法保存的数据没什么作用,只有在系统kill掉程序的情况下,再回到刚关闭的界面,回调了onRestoreInstanceState方法,这时onSaveInstanceState方法保存的数据,才发挥真正的作用,如何重现这种场景呢,利用DDMS替系统干这件坏事,kill掉你的程序:在按下HOME键后,系统已经调用你的onSaveInstanceState方法,打开DDMS找到你的程序进程,stop你的进程,再打开程序!

注意:Activity调用OnCreate方法来初始化界面,它在onRestoreInstanceState方法之前调用!

2、如果从MainActivity中通过Intent携带数据打开BActivity,BActivity界面被系统kill后,重新创建BActivity后之前携带的数据是会还原的,但该界面被杀之前对传过来的数据做的任何修改都作废!

3、onSaveInstanceState方法的参数(Bundle savedInstanceState) == onRestoreInstanceState方法参数(Bundle savedInstanceState)  == onCreate方法参数(Bundle savedInstanceState) ,第一次创建Activity时,调用onCreate方法,传进来的参数是为null,但如果出现被系统kill又被重建时调用onCreate的场景,onCreate方法的参数就是onSaveInstanceState方法和onRestoreInstanceState方法参数的值!通过在onCreate方法判断if(savedInstanceState
== null ) 是否被重建并存有数据!

4、界面上的View也都有onSaveInstanceState方法和onRestoreInstanceState方法,系统也是通过调用它们来存储界面和恢复界面的数据,系统会调用Activity对应的onSaveInstanceState方法之前调用界面View的onSaveInstanceState方法!

BActivity.java

private ArrayList<String> main = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.b);
if (savedInstanceState == null) {
Log.i("kill", "onCreate savedInstanceState = null 第一次创建BACtivity");
main = (ArrayList<String>)(getIntent().getExtras().get("main"));
Log.i("kill", "从MainActivity传过来的值 main = " +
""+main.toString());
//往传过来的ArrayList<String>对象填充数据
main.add("add String");

}else{
Log.i("kill", "BACtivity被杀后的重建 onCreate savedInstanceState的值 = " +
"onSaveInstanceState savedInstanceState的值 = onRestoreInstanceState" +
"savedInstanceState 的值= "+savedInstanceState.getString("save"));
main = (ArrayList<String>)(getIntent().getExtras().get("main"));
Log.i("kill", "BACtivity被杀后的重建 获得之前从MainActivity传过来的值 main=" +
""+main.toString());

}

}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
Log.i("kill", "BACtivity的onRestoreInstanceState方法被调用"+main.toString());
savedInstanceState.getString("save");
}

@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
Log.i("kill", "BACtivity的onSaveInstanceState方法被调用 存在main中的数据  = "+main.toString());
outState.putString("save", "come from onSaveInstanceState");
}

CustomView.java:只是继承了Button,重写了Button的onSaveInstanceState方法和onRestoreInstanceState方法

@Override
public Parcelable onSaveInstanceState() {
// TODO Auto-generated method stub
Log.i("kill", "CustomView onSaveInstanceState被调用");
return super.onSaveInstanceState();
}

@Override
public void onRestoreInstanceState(Parcelable state) {
// TODO Auto-generated method stub
Log.i("kill", "CustomView onRestoreInstanceState被调用");
super.onRestoreInstanceState(state);
}

5、从BActivity打开CActivity用StartActivityForResult方法要求CActivity finish时回传数据回BActivity,在跳转到CActivity后BActivity被系统Kill了,当CActivity finish时,系统重建BActivity,onActivityResult方法依然能收到上个界面回传的数据!(这个场景的出现就是在CActivity界面时用DDMS kill程序,重建CActivity再从CActivity回到BActivity就可以看到BActivity被重建,依然可以获得CActivity回传的数据)代码

BACtivity.java

Button bBtn = (Button)findViewById(R.id.b_btn);
bBtn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(BActivity.this, CActivity.class);
startActivityForResult(intent, 0);
}
});


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (isKill) {
Log.i("kill", "BACtivity被kill后重新创建的值 =" +
""+data.getExtras().getString("c"));
}else{
Log.i("kill", "BACtivity没被kill调用的值=" +
""+data.getExtras().getString("c"));
}
}


CActivity.java

Button cBtn = (Button)findViewById(R.id.c_btn);
cBtn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// finish自己,并回传数据给BActivity
Intent data = new Intent();
data.putExtra("c", "comfrom CActivity");
CActivity.this.setResult(Activity.RESULT_OK, data);
finish();
}
});

结论:

1、从A界面-->B界面-->C界面,用A界面通过Intent传过来的数据,即使B界面到C界面后B界面被杀了,再回到B界面,B界面还是拿得到A界面传过来的数据,但还是原始Intent的数据,如果B界面在被杀之前对Intent数据加工,通过onSaveInstanceState存储,通过onRestoreInstanceState统一处理了,那么就要绕过之前A界面通过Intent传过来的原始数据的干扰。

2、B界面-->C界面,B界面被kill了,C界面finish后,系统重建B界面,依然能拿到C界面回传的数据。

3、注意onCreate(Bundle saveInstanceSate)方法参数Bundle saveInstanceSate的作用

4、View也有onSaveInstanceState方法和onRestoreInstanceState方法

源代码http://download.csdn.net/detail/ak5700/6661497