应用在运行的过程中如果设备的配置发生变化(如屏幕方向、键盘可用性及语言),Android系统会重启正在运行的Activity以利用与新的设备配置相匹配的备用资源来加载应用。重启过程中(先后调用Activity的onDestroy()和onCreate()方法),先前Activity当中未被保存的数据资源会丢失。为了避免数据因Activity的重启而丢失,可以通过以下两种方式来对数据进行保存:

调用onSaveInstanceState()方法。

       onSaveInstanceState(Bundle outState)方法有一个Bundle类型的参数。在onSaveInstanceState()方法中,我们通过调用Bundle对象的putXXX()方法,将Activity中数据和变量的值保存在Bundle对象当中。之后Activity重启时会再次调用onCreate(Bundle savedInstanceState)方法,该方法中也有一个Bundle类型的参数,调用该Bundle对象的getXXX()方法即可得到通过onSaveInstanceState()方法保存的数据。此方法主要适用于需要保存的数据较少并且较简单的情形。若重启Activity时需要恢复大量的数据,或者需要重新建立网络连接和执行其它一些密集的操作,使用Bundle来保存和恢复数据可能会给用户留下应用运行缓慢的体验。在这种情况下,则可通过下面这种方式来减轻重新初始化Activity的负担。

     2. 通过保留Fragment来对数据进行保存。

       要在应用的配置变更时将有状态的对象保留在片段中,需要进行以下操作:

          1. 创建一个Fragment的子类并声明对有状态对象的引用;

          2. 在创建的片段中调用setRetainInstance(boolean);

          3. 将片段添加到Activity;

          4. 重启Activity后,使用FragmentManager得到片段并获取保存的对象。

         例如,按以下方式定义片段:

public class RetainedFragment extends Fragment{

    private MyDataObject data;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setRetainInstance(true);
    }
    public void setData(MyDataObject data) {
        this.data = data;
    }

    public MyDataObject getData() {
        return data;
    }
}
注意:切勿传递与Activity绑定的对象,例如:Drawable、Adapter、View或其他任何与Context关联的对象。否则,它将泄漏原始Activity实例的所有视图和资源。(泄漏资源意味着应用将继续持有这些资源,但是无法对其进行垃圾回收,因此可能会丢失大量内存)。

         然后,使用FragmentManager将定义的片段添加到Activity,并将需要保存状态的对象传入Fragment。当配置变更重新启动Activity时,我们可以获取片段中的数据对象。Activity的代码如下所示:

public class MyActivity extends Activity{

    private RetainedFragment dataFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        FragmentManager fm = getFragmentManager();
        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

        if (dataFragment == null) {
            dataFragment = new DataFragment();
            fm.beginTransaction().add(dataFragment, “data”).commit();
            dataFragment.setData(loadMyData());
        }
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dataFragment.setData(collectMyLoadedData());
    }
}