activity 异常被杀死数据保存的处理

从界面跳转后被系统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

时间: 2024-10-11 22:08:55

activity 异常被杀死数据保存的处理的相关文章

Activity数据保存探索

在开发中发现一个问题:当一个我通过Intent开启一个前面已经打开的activty的界面时, 新打开的activity的状态会丢失.当时,当我直接按home减将acitvity置于后台,然后重新打开这个activity的时候,发现此时的activity的状态是退出之前的状态.但是,我现在我想达到的目的是,不管是以什么方式打开这个活动,我都想要他恢复到之前的acitvity状态,而不是新开一个新的activity.于是针对这现象,我寻求解决方案. 利用onSaveInstanceState和onR

Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复

Android中的状态保存和恢复 Android中的状态保存和恢复, 包括Activity和Fragment以及其中View的状态处理. Activity的状态除了其中的View和Fragment的状态之外, 还需要用户手动保存一些成员变量. Fragment的状态有它自己的实例状态和其中的View状态, 因为其生命周期的灵活性和实际需要的不同, 情况会多一些. 根据源码, 列出了Fragment中实例状态和View状态保存和恢复的几个入口, 便于分析查看. 最后专门讲了WebView状态保存和

安卓第二天笔记-数据保存

安卓第二天笔记--数据保存 1.保存数据私有文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent&

Android 数据保存

Android数据保存方法 android数据保存主要保存以下三种: 1.共享参数文件中保存简单的键值对数据: 2.保存任意的文件数据到Android的文件系统中: 3.使用SQLite数据库管理 保存键值集 通过使用SharePreferences API来保存简单的键值对数据. 共享参数文件的获取或创建: 可以通过以下两种方法来获取: getSharedPreferences()  该方法需要提供一个共享参数文件的名称标识,该方法可以在任意Context中调用 getPreferences(

Hibernate数据保存操作方法的原理对比

Interface Session All Superinterfaces: Serializable All Known Subinterfaces: EventSource, Session All Known Implementing Classes: SessionImpl public interface Session  extends Serializable Java应用程序与Hibernate之间的主要运行时接口.它是抽象了持久化服务概念的核心抽象API类. Session的生

Fragment not attached to Activity 异常

1.关于Fragment(XXFragment) not attached to Activity 异常.出现该异常,是因为Fragment的还没有Attach到Activity时,调用了如getResource()等,需要上下文Content的函数.解决方法,就是等将调用的代码写在OnStart()中.网上还有几处这样的参考:http://stackoverflow.com/questions/10919240/fragment-myfragment-not-attached-to-activ

活动被回收和数据保存

一.问题由来:如果一个Activity处于停止状态,那么在内存紧张的时候,该活动就有可能被回收,这个时候,回退到该Activity,将会启动onCreate,之前在该Activity做的数据修改,将会丢失. 二.系统在回收活动时,会调用onSaveInstanceState方法,重载该方法,保存数据,在onCreate中再取出数据 // 保存数据@Overrideprotected void onSaveInstanceState(Bundle outState) { super.onSaveI

ClientDataset+TDataSetProvider的数据保存问题

看到一篇介绍ClientDataSet和TDataSetProvider,非常精彩,特此保存. ================================================================================= 前台:D7或D2005; DBExpress连接组件:TSqlConnection,TSqlQuery ,TDataSetProvider,TClientDataSet;后台:SQL Server 2000; 更新数据的命令:DataSet

Delphi:ClientDataset+TDataSetProvider的数据保存问题

看到一篇介绍ClientDataSet和TDataSetProvider,非常精彩,特此保存. =========================================================================== TClientDataSet用法 第十一章 TClientDataSet 与TTable.TQuery一样,TClientDataSet也是从TDataSet继承下来的,它通常用于多层体系结构的客户端.TClientDataSet最大的特点是它不依赖于