a、如果是少量数据,可以通过onSaveInstanceState()和onRestoreInstanceState()进行保存与恢复。
Android会在销毁你的Activity之前调用onSaveInstanceState()方法,于是,你可以在此方法中存储关于应用状态的数据。然后你可以在onCreate()或onRestoreInstanceState()方法中恢复。
b、如果是大量数据,使用Fragment保持需要恢复的对象。
c、自已处理配置变化。
注:getLastNonConfigurationInstance()已经被弃用,被上述方法二替代。
2、难点
假设当前Activity在onCreate中启动一个异步线程去夹在数据,当然为了给用户一个很好的体验,会有一个ProgressDialog,当数据加载完成,ProgressDialog消失,设置数据。
这里,如果在异步数据完成加载之后,旋转屏幕,使用上述a、b两种方法都不会很难,无非是保存数据和恢复数据。
但是,如果正在线程加载的时候,进行旋转,会存在以下问题:
a)此时数据没有完成加载,onCreate重新启动时,会再次启动线程;而上个线程可能还在运行,并且可能会更新已经不存在的控件,造成错误。
b)关闭ProgressDialog的代码在线程的onPostExecutez中,但是上个线程如果已经杀死,无法关闭之前ProgressDialog。
下面我将使用几个例子,分别使用上面的3种方式,和如何最好的解决上述的问题。
本文相关源码下载地址:
------------------------------------------分割线------------------------------------------
具体下载目录在 /2015年资料/8月/8日/Android 屏幕旋转 处理 AsyncTask 和 ProgressDialog 的最佳方案/
------------------------------------------分割线------------------------------------------
3、使用onSaveInstanceState()和onRestoreInstanceState()进行数据保存与恢复
代码:
package com.example.zhy_handle_runtime_change;
import java.util.ArrayList;
import java.util.Arrays;
import android.app.DialogFragment;
import android.app.ListActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
/**
?* 不考虑加载时,进行旋转的情况,有意的避开这种情况,后面例子会介绍解决方案
?* @author zhy
?*
?*/
public class SavedInstanceStateUsingActivity extends ListActivity
{
?private static final String TAG = "MainActivity";
?private ListAdapter mAdapter;
?private ArrayList mDatas;
?private DialogFragment mLoadingDialog;
?private LoadDataAsyncTask mLoadDataAsyncTask;
?@Override
?public void onCreate(Bundle savedInstanceState)
?{
? super.onCreate(savedInstanceState);
? Log.e(TAG, "onCreate");
? initData(savedInstanceState);
?}
?/**
? * 初始化数据
? */
?private void initData(Bundle savedInstanceState)
?{
? if (savedInstanceState != null)
? ?mDatas = savedInstanceState.getStringArrayList("mDatas");
? if (mDatas == null)
? {
? ?mLoadingDialog = new LoadingDialog();
? ?mLoadingDialog.show(getFragmentManager(), "LoadingDialog");
? ?mLoadDataAsyncTask = new LoadDataAsyncTask();
? ?mLoadDataAsyncTask.execute();
? ?
? } else
? {
? ?initAdapter();
? }
?}
?/**
? * 初始化适配器
? */
?private void initAdapter()
?{
? mAdapter = new ArrayAdapter(
? ? SavedInstanceStateUsingActivity.this,
? ? android.R.layout.simple_list_item_1, mDatas);
? setListAdapter(mAdapter);
?}
?@Override
?protected void onRestoreInstanceState(Bundle state)
?{
? super.onRestoreInstanceState(state);
? Log.e(TAG, "onRestoreInstanceState");
?}
?@Override
?protected void onSaveInstanceState(Bundle outState)
?{
? super.onSaveInstanceState(outState);
? Log.e(TAG, "onSaveInstanceState");
? outState.putSerializable("mDatas", mDatas);
?}
?private class LoadDataAsyncTask extends AsyncTask
?{
? @Override
? protected Void doInBackground(Void... params)
? {
? ?mDatas = generateTimeConsumingDatas();
? ?return null;
? }
? @Override
? protected void onPostExecute(Void result)
? {
? ?mLoadingDialog.dismiss();
? ?initAdapter();
? }
?}
?@Override
?protected void onDestroy()
?{
? Log.e(TAG, "onDestroy");
? super.onDestroy();
?}
}
界面为一个ListView,onCreate中启动一个异步任务去加载数据,这里使用Thread.sleep模拟了一个耗时操作;当用户旋转屏幕发生重新启动时,会onSaveInstanceState中进行数