• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案,androidasynctask

Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案,androidasynctask

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案,androidasynctask等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案,androidasynctask


一、概述

运行时变更就是设备在运行时发生变化(例如屏幕旋转、键盘可用性及语言)。发生这些变化,Android会重启Activity,这时就需要保存activity的状态及与activity相关的任务,以便恢复activity的状态。

为此,google提供了三种解决方案:

下面会逐一介绍三种情况,其实保存一些变量对象很简单,难的是当Activity创建异步线程去加载数据时,旋转屏幕时,怎么保存线程的状态。比如,在线程的加载过程中,旋转屏幕,就会存在问题:此时数据没有完成加载,onCreate重新启动时,会再次启动线程;而上个线程可能还在运行,并且可能会更新已经不存在的控件,造成错误。下面会一一解决这些问题。本文较长,主要是代码多,可以先下载demo,源码下载:http://download.csdn.net/detail/jycboy/9720486对比着看。

 二、使用onSaveInstanceState,onRestoreInstanceState?

代码如下:

/**
 * 使用onSaveInstanceState,onRestoreInstanceState;
 * 在这里不考虑没有加载完毕,就旋转屏幕的情况。
 * @author 超超boy
 *
 */
public class SavedInstanceStateActivity extends ListActivity
{
	private static final String TAG = "MainActivity";
	private ListAdapter mAdapter;
	private ArrayList<String> 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();
			//mLoadDataAsyncTas
		} else
		{
			initAdapter();
		}
	}

	/**
	 * 初始化适配器
	 */
	private void initAdapter()
	{
		mAdapter = new ArrayAdapter<String>(
				SavedInstanceStateActivity.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);

	}
	/**
	 * 模拟耗时操作
	 * 
	 * @return
	 */
	private ArrayList<String> generateTimeConsumingDatas()
	{
		try
		{
			Thread.sleep(3000);
		} catch (InterruptedException e)
		{   e.printStackTrace();
		}
		return new ArrayList<String>(Arrays.asList("通过Fragment保存大量数据",
				"onSaveInstanceState保存数据",
				"getLastNonConfigurationInstance已经被弃用", "RabbitMQ", "Hadoop",
				"Spark"));
	}

	private class LoadDataAsyncTask extends AsyncTask<Void, Void, Void>
	{
		@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中进行数据的存储,在onCreate中对数据进行恢复,免去了不必要的再加载一遍。

运行结果:

12-24 20:13:41.814 1994-1994/? E/MainActivity: onCreate
12-24 20:13:46.124 1994-1994/? E/MainActivity: onSaveInstanceState
12-24 20:13:46.124 1994-1994/? E/MainActivity: onDestroy
12-24 20:13:46.154 1994-1994/? E/MainActivity: onCreate
12-24 20:13:46.164 1994-1994/? E/MainActivity: onRestoreInstanceState

当正常加载数据完成之后,用户不断进行旋转屏幕,log会不断打出:onSaveInstanceState->onDestroy->onCreate->onRestoreInstanceState,验证Activity重新启动,但是我们没有再次去进行数据加载。

如果在加载的时候,进行旋转,则会发生错误,异常退出(退出原因:dialog.dismiss()时发生NullPointException,因为与当前对话框绑定的FragmentManager为null,在这里这个不是关键)。

效果图:

 

三、使用Fragment保留对象,恢复数据

果重启 Activity 需要恢复大量数据、重新建立网络连接或执行其他密集操作,依靠系统通过onSaveInstanceState() 回调为您保存的 Bundle,可能无法完全恢复 Activity 状态,因为它并非设计用于携带大型对象(例如位图),而且其中的数据必须先序列化,再进行反序列化,这可能会消耗大量内存并使得配置变更速度缓慢。 在这种情况下,如果 Activity 因配置变更而重启,则可通过保留 Fragment 来减轻重新初始化 Activity 的负担。此片段可能包含对您要保留的有状态对象的引用。

当 Android 系统因配置变更而关闭 Activity 时,不会销毁您已标记为要保留的 Activity 的片段。 您可以将此类片段添加到 Activity 以保留有状态的对象。

要在运行时配置变更期间将有状态的对象保留在片段中,请执行以下操作:

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

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;
    }
} 

注意:尽管您可以存储任何对象,但是切勿传递与 Activity 绑定的对象,例如,Drawable、Adapter、View 或其他任何与 Context 关联的对象。否则,它将使Activity无法被回收造成内存泄漏。(泄漏资源意味着应用将继续持有这些资源,但是无法对其进行垃圾回收,因此可能会丢失大量内存)

下面举一个实际的例子:

1.RetainedFragment

public class RetainedFragment extends Fragment
{
	// data object we want to retain
	private Bitmap 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(Bitmap data)
	{
		this.data = data;
	}

	public Bitmap getData()
	{
		return data;
	}
}

只是保持Bitmap对象的引用,你可以用Fragment保存多个对象。

2.FragmentRetainDataActivity:

public class FragmentRetainDataActivity extends Activity
{

	private static final String TAG = "FragmentRetainData";
	private RetainedFragment dataFragment;
	private DialogFragment mLoadingDialog;
	private ImageView mImageView;
	private Bitmap mBitmap;
	BitmapWorkerTask bitmapWorkerTask;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Log.e(TAG, "onCreate");

		// 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 RetainedFragment();
			fm.beginTransaction().add(dataFragment, "data").commit();
		}
		// the data is available in dataFragment.getData()
		m



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案,androidasynctask

相关文章

  • 2017-05-26安卓开发与分析者的利器--安卓右键工具
  • 2017-05-26Android开发技巧——定制仿微信图片裁剪控件
  • 2017-05-26android TextView 设置字体大小,androidtextview
  • 2017-05-26可展开的列表组件——ExpandableListView深入解析,expandablelist展开
  • 2017-05-26自定义加载loading view动画组件的使用。,loadingview
  • 2017-05-26Android之解析XML,androidxml
  • 2017-05-26分析google的multidex库,googlemultidex库
  • 2017-05-26Android Studio 1.5.1 JNI 编程
  • 2017-05-26XAMARIN.ANDROID SIGNALR 实时消息接收发送示例,xamarinsignalr
  • 2017-05-26移动端web头部header通用写法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • android--获取屏幕高宽度工具类,android--工具类
    • 4.4.2 ContentProvider再探——Document Provider
    • Android中使用ExpandableListView实现好友分组,expandablelistview
    • Android网络编程的Socket通信总结
    • 关于TCP MSS的内核设置
    • [Android]动态加载/热部署框架汇总,android框架
    • 从头开始学RecyclerView(六)LayoutManager
    • Android之上下文context,androidcontext
    • 文件缓存(配合JSON数组),缓存配合json数组
    • Android之ContentProvider数据存储,contentprovider

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有