Activity中使用注解进行状态保存

转载请注明出处: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注解和反射的,还是去查查其他的资料吧!

时间: 2024-10-27 03:49:03

Activity中使用注解进行状态保存的相关文章

Android中通过注解代替findViewById方法

尊重原创 http://write.blog.csdn.net/postedit/26507351 这篇文章主要讲解注解实现findViewById的功能,首先我们来熟悉一下在java中怎么定义一个注解和解析一个注解 注解的概念是在jdk5.0中提出来的,在java.lang的包中已经定义了三个注解:Override,Deprecated,SuppressWarnings Override相信大家非常熟悉,就是表明这个方法是改写了父类的方法 Deprecated表示在新版本的 jdk中已经不建议

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

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

activity状态保存的bundl对象存放位置的思考

我们知道,当activity被异常终止时,可以把一些信息保存到bundle对象中,在下次启动时恢复. 那么,这个bundle对象是保存在哪里的呢? 这种状态保存的方法针对的是activity而不是进程,那么我们就可以猜测,这个对象是保存在内存中的,而不是存储设备上. 如果想对于进程进行数据保存等,应该使用外部存储来保存,在初始化的时候读取并恢复.

Activity,Fragment状态保存

Activity android:alwaysRetainTaskState     用法 用来标记Activity所在的Task的状态是否总是由系统来保持--"true",表示总是:"false",表示在某种情形下允许系统恢复Task 到它的初始化状态.默认值是"false".这个特性只针对Task的根Activity有意义:对其它Activity来说,忽略之.     一般来说,特定的情形如当用户从主画面重新选择这个Task时,系统会对这个T

Activity具体解释(生命周期、以各种方式启动Activity、状态保存,全然退出等)

一.什么是Activity? 简单的说:Activity就是布满整个窗体或者悬浮于其它窗体上的交互界面.在一个应用程序中通常由多个Activity构成,都会在Manifest.xml中指定一个主的Activity,例如以下设置 <actionandroid:name="android.intent.action.MAIN" /> 当程序第一次执行时用户就会看这个Activity,这个Activity能够通过启动其它的Activity进行相关操作.当启动其它的Activity

Android基础部分再学习---activity的状态保存

主要是bundle   这个參数 參考地址:http://blog.csdn.net/lonelyroamer/article/details/18715975 学习Activity的生命周期,我们知道,当Activity进入到paused或者stopped状态后,这个Activity的状态仍然保存着. 由于这个Activity对象仍然保存在内存中.它的全部信息和状态仍然是存在的.当这个Activity再次返回到前台是,它仍然保持着离开时候的样子. 然而.假设Activity进入到了后台.系统为

Activity详细解释(生命周期、以各种方式启动Activity、状态保存,等完全退出)

一.什么是Activity? 简单的说:Activity或者悬浮于其它窗体上的交互界面. 在一个应用程序中通常由多个Activity构成.都会在Manifest.xml中指定一个主的Activity,例如以下设置 <actionandroid:name="android.intent.action.MAIN" /> 当程序第一次执行时用户就会看这个Activity,这个Activity能够通过启动其它的Activity进行相关操作.当启动其它的Activity时这个当前的这

Activity生命周期与状态保存

弹出系统对话框,程序仍部分可见 onPause 对话框消失时 onResume 调用一个新的Activity,老的Activity不可见时 onPause->onStop 从新的Activity返回时 onRestart->onStart->onResume 正常运行的Activity正常结束时 onPause->onStop->onDestroy onResume 这不是用来判断Activity是否对用户可见的最好方法.即使这个方法被调用后,也可能有一些系统窗口在我们的Ac

Android总结 - Activity任务和返回栈、保存Activity的状态

任务和返回栈 一个应用程序当中通常都会包含很多个Activity,每个Activity都应该设计成为一个具有特定的功能,并且可以让用户进行操作的组件.另外,Activity之间还应该是可以相互启动的.比如,一个邮件应用中可能会包含一个用于展示邮件列表的Activity,而当用户点击了其中某一封邮件的时候,就会打开另外一个Activity来显示该封邮件的具体内容. 除此之外,一个Activity甚至还可以去启动其它应用程序当中的Activity.打个比方,如果你的应用希望去发送一封邮件,你就可以定