转载请注明出处:http://blog.csdn.net/allen315410/article/details/43567229
问题描述
一般开发中,当调用Activity生命周期方法onPause()和onStop()方法后,Activity的实例并没有被直接销毁,它仍然保存在内存中,Activity里面所有的信息和状态数据都将保存下来,当这个Activity重新回到前台的时候,所有的数据都会得到保留并且可被使用。
但是在一些特殊情况下,例如设备上装载了“XX大师”“XX助手”等清理内存的工具时,也有可能直接干掉我们后台的Activity,还有一种情况就是当系统的内存不足时,垃圾回收机制被自动回收到我们在之前已经onPause()和onStop()的Activity,这样的话,Activity里面的信息和状态数据都消失了,当重新启动Activity时,就找不到数据。这时,一般情况我们程序员可以在Activity销毁之前将需要保留下来的数据进行本地化保存,SharedPrefence是个不错的选择的,但是这样做起来似乎比较麻烦一点。
一般解决办法
还有一种方法就是使用Activity里的onSaveInstanceState(Bundle outState)方法里做一些保存数据的工作,onSaveInstanceState(Bundle outState)方法传递一个Bundle对象,我们使用Bundle对象put一些需要保存的数据进去,当我们重新将Activity放到前台工作时,在onCreate()方法中先判断Bundle是否为空,根据判断条件来取舍数据来使用,或者直接重写Activity下的onRestoreInstanceState(Bundle
savedInstanceState)方法,在这个方法下取数据。例如:
public class ExampleActivity1 extends Activity { private String mState; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { mState = savedInstanceState.getString("state"); } } // Activity被回收前,会调用这个方法,保存数据 @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("state", mState); } // 也可以在这个方法里恢复数据 @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mState = savedInstanceState.getString("state"); } }
以上几行简单的代码可以解决Activity状态保存问题,但是有个问题出现了,如果我们需要保存的数据不止一两个一两种数据类型呢?也可以,我们可以不停的putXXX()不同的数据到Bundle中,然后在不停的getXXX()不同的数据出来使用。可行性是没有任何问题的,但是稍微显得有些繁琐啊,下面就是使用注解来简化了这样的一些不必要的重复性的操作,大大简化了源码的书写。
使用注解保存状态信息
下面是完整的实现代码,不难懂,为了便于在Activity里面使用,要创建一个Activity的基类BaseActivity,在基类中将这些代码写上,以后没创建一个新的Activity实例都要继承BaseActivity,保证每个Activity都有相应的状态信息保存方法。
package com.example.activitystatesave; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import android.app.Activity; import android.os.Bundle; import android.os.Parcelable; import android.util.Log; public class BaseActivity extends Activity { private final String TAG = "BaseActivity"; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface SavedInstanceState { } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 恢复数据 if (savedInstanceState != null) { restoreInstanceState(savedInstanceState); } } /** * 保存状态 */ @Override protected void onSaveInstanceState(Bundle outState) { Field[] fields = this.getClass().getDeclaredFields(); Field.setAccessible(fields, true); Annotation[] ans; for (Field f : fields) { ans = f.getDeclaredAnnotations(); for (Annotation an : ans) { if (an instanceof SavedInstanceState) { try { Object o = f.get(this); if (o == null) { continue; } String fieldName = f.getName(); if (o instanceof Integer) { outState.putInt(fieldName, f.getInt(this)); } else if (o instanceof String) { outState.putString(fieldName, (String) f.get(this)); } else if (o instanceof Long) { outState.putLong(fieldName, f.getLong(this)); } else if (o instanceof Short) { outState.putShort(fieldName, f.getShort(this)); } else if (o instanceof Boolean) { outState.putBoolean(fieldName, f.getBoolean(this)); } else if (o instanceof Byte) { outState.putByte(fieldName, f.getByte(this)); } else if (o instanceof Character) { outState.putChar(fieldName, f.getChar(this)); } else if (o instanceof CharSequence) { outState.putCharSequence(fieldName, (CharSequence) f.get(this)); } else if (o instanceof Float) { outState.putFloat(fieldName, f.getFloat(this)); } else if (o instanceof Double) { outState.putDouble(fieldName, f.getDouble(this)); } else if (o instanceof String[]) { outState.putStringArray(fieldName, (String[]) f.get(this)); } else if (o instanceof Parcelable) { outState.putParcelable(fieldName, (Parcelable) f.get(this)); } else if (o instanceof Serializable) { outState.putSerializable(fieldName, (Serializable) f.get(this)); } else if (o instanceof Bundle) { outState.putBundle(fieldName, (Bundle) f.get(this)); } } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); } catch (IllegalAccessException e) { Log.e(TAG, e.getMessage()); } catch (Exception e) { Log.e(TAG, e.getMessage()); } } } } super.onSaveInstanceState(outState); } /** * 在这里恢复数据 * * @param savedInstanceState */ private void restoreInstanceState(Bundle savedInstanceState) { Field[] fields = this.getClass().getDeclaredFields(); Field.setAccessible(fields, true); Annotation[] ans; for (Field f : fields) { ans = f.getDeclaredAnnotations(); for (Annotation an : ans) { if (an instanceof SavedInstanceState) { try { String fieldName = f.getName(); Class cls = f.getType(); if (cls == int.class || cls == Integer.class) { f.setInt(this, savedInstanceState.getInt(fieldName)); } else if (String.class.isAssignableFrom(cls)) { f.set(this, savedInstanceState.getString(fieldName)); } else if (Serializable.class.isAssignableFrom(cls)) { f.set(this, savedInstanceState.getSerializable(fieldName)); } else if (cls == long.class || cls == Long.class) { f.setLong(this, savedInstanceState.getLong(fieldName)); } else if (cls == short.class || cls == Short.class) { f.setShort(this, savedInstanceState.getShort(fieldName)); } else if (cls == boolean.class || cls == Boolean.class) { f.setBoolean(this, savedInstanceState.getBoolean(fieldName)); } else if (cls == byte.class || cls == Byte.class) { f.setByte(this, savedInstanceState.getByte(fieldName)); } else if (cls == char.class || cls == Character.class) { f.setChar(this, savedInstanceState.getChar(fieldName)); } else if (CharSequence.class.isAssignableFrom(cls)) { f.set(this, savedInstanceState.getCharSequence(fieldName)); } else if (cls == float.class || cls == Float.class) { f.setFloat(this, savedInstanceState.getFloat(fieldName)); } else if (cls == double.class || cls == Double.class) { f.setDouble(this, savedInstanceState.getDouble(fieldName)); } else if (String[].class.isAssignableFrom(cls)) { f.set(this, savedInstanceState.getStringArray(fieldName)); } else if (Parcelable.class.isAssignableFrom(cls)) { f.set(this, savedInstanceState.getParcelable(fieldName)); } else if (Bundle.class.isAssignableFrom(cls)) { f.set(this, savedInstanceState.getBundle(fieldName)); } } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); } catch (IllegalAccessException e) { Log.e(TAG, e.getMessage()); } catch (Exception e) { Log.e(TAG, e.getMessage()); } } } } } }
以上是全部的BaseActivity的源码,使用时创建新的Activity extends BaseActivity,需要哪些成员变量Filed的数据得到保存,就在哪些成员变量Filed上加上这个定义好的注解。关于注解的基础知识,可以先找其他的资料看一下,也可以参考http://blog.csdn.net/allen315410/article/details/16829801,但是这里讲的也特别基础,希望多了解Java注解和反射的,还是去查查其他的资料吧!