覆盖onSaveInstanceState(...)方法并不仅仅用于处理设备旋转相关的问题。用户离开当前activity管理的用户界面,或Android需要回收内存时,activity也会被销毁。基于用户体验考虑,Android从不会为了回收内存,而去销毁正在运行的activity。activity只有在暂停或停止状态下才可能会被销毁。此时,会调用onSaveInstanceState(...)方法。调用onSaveInstanceState(...)方法时,用户数据随即被保存在Bundle对象中。然后操作系统将Bundle对象放入activity记录中。
为便于理解activity记录,我们增加一个暂存状态(stashed state)到activity生命周期,如图3-13所示。
activity暂存后,Activity对象不再存在,但操作系统会将activity记录对象保存起来。这样,在需要恢复activit时,操作系统可以使用暂存的activity记录重新激活activity。注意,activity进入暂存状态并不一定需要调用onDestroy()方法。不过,onPause()和onSaveInstanceState(...)通 常 是 我 们 需 要 调 用 的 两 个 方 法 。 常 见 的 做 法 是 , 覆 盖onSaveInstanceState(...)方法,将数据暂存到Bundle对象中,覆盖onPause()方法处理其他需要处理的事情
一,保存销毁前的Activity数据
方法:protected void onSaveInstanceState(Bundle outState) ;通过bundle实现
重写方法保存数据的例子:
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.i(TAG, "onSaveInstanceState");
savedInstanceState.putInt(KEY_INDEX, mCurrentIndex);
}
取回书籍:先判断onSaveInstanceState是否为空,然后取回数据
if (savedInstanceState != null) {
mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);
}
以上,KEY_INDEX是个变量,mCurrentIndex是个按钮,以上函数的意思是将保存的变量值传到按钮上
二,切换新的Activity:
1. 新建Activity(包括JAVA,XML,manifest文件 )
通过AS的导引功能创建最基本的再根据需要添加内容
2. 切换Activty(基于Intent通讯)
例子: (如果是以fragment方式的话,切换Activity的方法放fragment里,而接受数据还是在新Activity里)
2.1 方式一: MainActivity.class是某个Activity类,启动它
Intent intent = new Intent(getActivity(),MainActivity.class);
startActivity(intent);
2.2 方式二:通过自定义类方法来创建(包含数据传递)
流程:
旧Activity启动Intent生成新Activity并将数据传递到其私有空间--新Acitiviy从其私有空间将数据取出
2.2.1 定义数据传递中介,在新Acitvity里
//用于Intent数据传输,该字符串用于标记Acitvity的私有空间
public static final String EXTRA_CRIME_ID =
"com.bignerdranch.android.criminalintent.crime_id";
2.2.2 自定义在新Activity类的创建Intent方法,里面实际的生成Intent的方法包含Acitivity上下文和新Acitvity类,实质还是和方式一一样
UUID只是为了接受包含数据的类的ID,保存注入在EXTRA_CRIME_ID里,可以借此ID找到数据类
//自定义的生成Intent类的方法,将数据ID推进Activity私有空间中
public static Intent newIntent(Context packageContext, UUID crimeId) {
Intent intent = new Intent(packageContext, MainActivity.class);
intent.putExtra(EXTRA_CRIME_ID, crimeId);
return intent;
}
2.2.3 在旧的Acitvity调用上述自定义方法,并传递数据类ID
Intent intent = MainActivity.newIntent(getActivity(), yCrime.getyID());
startActivity(intent);
2.2.4 从Acitivity的静态字符串标记的私有空间获取数据
//现在Intent方式是接受Crime,从Activity私有空间获取数据ID
// UUID crimeId = (UUID) getActivity().getIntent()
// .getSerializableExtra(MainActivity.EXTRA_CRIME_ID);
2.2.5 以数据ID找到数据类:
//以数据ID找到数据类,自定义方法,从数据模型中找到相应ID的数据类
yCrime = CrimeListLab.getyCrimeLab(getActivity()).getCrime(crimeId);
3. Activity间数据的传递(基于Intent通讯)
包括父Activity传子Activity,子Activity返父Activity
例子:基于fragment argument
注意:如果新旧fragment使用的同一数据对象,且一方有监听保存数据于数据对象,另一方有更新方法,则能实现同步更新,如果都有则可双向更新
优势在于Activity的私有空间标志私有化被保护,数据传递在fragment的私有空间里使用
流程:
旧Activity启动Intent生成新Activity并将数据传递到其私有空间--新Acitiviy创建新fragment并将数据传递到fragment的私有空间--fragment将其私有空间的数据取出
3.1
3.1.1 新Activity中
//用于fragment argument方式接受数据,以此字符串标记的Acitivity私有空间
private static final String EXTRA_CRIME_ID =
"com.bignerdranch.android.criminalintent.crime_id";
3.1.2 新Activity中
//自定义的生成Intent类的方法
//将数据传递进字符串标记的私有空间
public static Intent newIntent(Context packageContext, UUID crimeId) {
Intent intent = new Intent(packageContext, MainActivity.class);
intent.putExtra(EXTRA_CRIME_ID, crimeId);
return intent;
}
3.1.3 新fragment中
//fragment argument方式接受数据类ID的字符串,以此字符串标记的fragment的私有空间
private static final String ARG_CRIME_ID = "crime_id";
3.1.4 新fragment中
//fragment的自定义方法,
// 将数据类ID传递给fragment静态字符串标记的私有空间
// 创建fragment,并将私有空间和fragment关联
public static CrimeFragment newInstance(UUID crimeId) {
Bundle args = new Bundle();
//将数据传递给以此字符串标记私有空间
args.putSerializable(ARG_CRIME_ID, crimeId);
CrimeFragment fragment = new CrimeFragment();
//将私有空间传递给fragment
fragment.setArguments(args);
return fragment;
}
3.1.5 新Activity中createFragment()方法里
//根据fragment argument接受字符来获得一个数据类ID
UUID crimeId = (UUID) getIntent()
.getSerializableExtra(EXTRA_CRIME_ID);
//调用fragment的自定义方法,
// 将数据类ID传递给fragment静态字符串标记的私有空间
// 创建fragment,并将私有空间和fragment关联
return CrimeFragment.newInstance(crimeId);
3.1.6 启动:旧fragment中监听事件响应里(根据需要在需要的地方启动新Aitivity)
//直接用Activity所在类的方法生成Intent对象
//该方法为Activity自定义方法
Intent intent = MainActivity.newIntent(getActivity(), yCrime.getyID());
startActivity(intent);
3.1.7 最终接受:新fragment中OnCreate()方法里
//现在fragment argument方式是接受Crime,从fragment的静态字符串标记的私有空间获取数据ID
UUID crimeId = (UUID) getArguments().getSerializable(ARG_CRIME_ID);
//以数据ID找到数据类,自定义方法,从数据模型中找到相应ID的数据类
yCrime = CrimeListLab.getyCrimeLab(getActivity()).getCrime(crimeId);