在Activity创建和销毁这个过程中,相信大家都知道可以使用
onSaveInstanceState()
和
onRestoreInstanceState() 来保存和恢复App的状态,为用户提供较好的体验,当保存量较少的数据的时候,这个是个不二的选择,但是可能会遇到要保存的数据量较大的时候,界面切换是就会有些迟钝的感觉,会给用户带来不好的体验。官方文档给出的解决办法是:
- 保留一个持有之前界面状态的数据对象
- 由我们自己来处理这个运行时的变化
保留一个持有之前界面状态的数据对象
onSaveInstanceState()会对你存入的数据进行序列化和反序列化,所以会消耗较多的内存,如果你给他的数据量大了,就更加消耗内存。看文档给出的解决方案是给当前的Activity附上一个Fragment,再在这个Fragment中存放你要恢复Activity状态的数据。通过相应的设置,这个Fragment在Activity被销毁的时候仍然能够保留,所以当Activity被重新创建时,可以取得这个Fragment获取之前的状态数据。 这个特殊的Fragment需要做一下几件事:
官方示例:
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
public void setData(MyDataObject data) {
this.data = data;
}
public MyDataObject getData() {
return data;
}
}
public class MyActivity extends Activity {
private RetainedFragment dataFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
dataFragment = (RetainedFragment) fm.findFragmentByTag(“data”);
// create the fragment and data the first time
if (dataFragment == null) {
// add the fragment
dataFragment = new DataFragment();
fm.beginTransaction().add(dataFragment, “data”).commit();
// load the data from the web
dataFragment.setData(loadMyData());
}
// the data is available in dataFragment.getData()
...
}
@Override
public void onDestroy() {
super.onDestroy();
// store the data in the fragment
dataFragment.setData(collectMyLoadedData());
}
}
警告:这里保存的对象不能是与上下文关联的,如果是与Context关联的,之前被销毁的Activity的views,resources都不能被GC,就会造成内存的泄露。
自己来处理这个运行时的变化
如果自己来控制配置变化的话需要对在manifest中对Activity进行相应的设置,常遇到的就是方向的改变和键盘事件,具体可见
android:configChanges
: 低于API LEVEL13的情况:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
API LEVEL13后要方向改变除了orientation还有个screensize:
<activity
android:screenOrientation="sensor"
android:configChanges="orientation|screenSize|keyboardHidden"/>
当方向发生变化时,会回调onConfigurationChanged这个方法,这里就可以自己来处理这些变化。