处理方向更改的最佳做法:Android

时间:2013-12-11 09:10:46

标签: android multithreading orientation fragment

我正在通过各种实践来处理线程和AsyncTask的方向更改。我遇到了以下解决方案:

  1. Attach-detach model:在保留实例的同时,将活动附加到线程和AsyncTask。 (来源:12

  2. 无头片段方式:使用非UI /无头片段执行所有与线程相关的操作,并在配置更改时保留其实例。 (来源:12

  3. 还有其他方法可以处理这种情况吗?建议的做法是什么?我问这个是因为我在Android文档的任何地方都找不到通用的解决方案。

6 个答案:

答案 0 :(得分:43)

一些摘要

上面提到的几种方法都是很好的做法,但我想我可以用简短的解释来总结它们。下面是目前用于http网络,异步工作/线程和缓存的一些最流行的库。

我当前的项目(只是偏好)

我个人目前正在使用 Otto Loaders Volley Ormlite 以及基于的网络堆栈 Apache Service。我希望在某些时候用 Volley Retrofit 替换网络堆栈,最后可能 Robospice

个人非常喜欢Otto和Volley


RoboSpice(模块化)

改造(REST)

排球(网络数据和图片)

毕加索(图片)

加载程序(Android)

  • 得到很好的支持
  • 坚持通过方向更改并保存/加载片段状态
  • 可能很难做对
  • 没有缓存

AsyncTask(Android)

  • 来自UI线程的后台工作的简单方法
  • 必须取消
  • 并注意在活动或片段被拆除后返回的任务。

奥托(活动巴士)

  • https://github.com/square/otto
  • 使组件和片段之间的同步工作变得容易的事件总线
  • 非常强大的@Produce能力保留最后一个事件,可以根据需要为任何新感兴趣的公共汽车订户生成

无头碎片(?)

  • 除了Vogella的教程之外,我个人从未见过这个用途,所以我不确定这个。

服务(Android)

  • 旧学校方式
  • 终极控制,你必须自己做一切
  • 通常与Appache或HURL客户端一起使用
  • 通过Intents传递Parcels

答案 1 :(得分:7)

为什么不尝试Loaders,特别是AsyncTaskLoader?它们可通过Support Library用于预蜂窝,并与活动/片段生命周期完美匹配。以下是官方摘要:

  
      
  • 每个活动和片段都可以使用它们。
  •   
  • 他们提供异步数据加载。
  •   
  • 他们会监控数据来源,并在内容发生变化时提供新结果。
  •   
  • 在配置更改后重新创建时,它们会自动重新连接到上一个加载程序的游标。因此,他们不需要重新查询他们的数据。
  •   

答案 2 :(得分:4)

我们实际上正在使用 RoboSpice库。它仅在提供RequestListeners对象的服务上运行。

第一种方法的问题(保持AsyncTask之间的引用)是您可能会生成内存泄漏,因为当您的AsyncTasks保存您的活动引用时,它们将是不是垃圾收集。密切关注这个只是分析您的应用程序检查堆大小一遍又一遍地旋转相同的活动。你的堆应该在正常的参数中增长(有一段时间你的对象必须被垃圾收集与新对象同时存在)但是当GC运行时你的RAM分配应该落到你在开始。

因此,如果我必须推荐一些东西,那将是下一件事:

活动管理API调用和流程(使用RoboSpice,让de UI旋转) 使用retainInstance为true的Fragments中的简单屏幕。这让你可以直接将DTO传递给你的片段,你必须只管理顶层活动的状态。

答案 3 :(得分:3)

如果主要关注处理asyncTask,即每次更改方向时都不愿意下载数据,那么您可以尝试这样做 -

(1)在创建此类之前初始化任何值..

Boolean android_hacker = false;

(2)现在,当您完成在AsyncTask类上下载数据时,请将该值设置为true

android_hacker = true;

这里使用模型和数组适配器类维护所有数据

(3)现在每次改变方向,然后像这样检查

if( android_hacker = true ){

// Use your saved instance ..

}else{

// Download data as it is yet not downloaded ..

}

希望有所帮助......

答案 4 :(得分:2)

您可以通过多种方式尝试AsyncTask。如果你试图找到最佳实践,AsyncTask不是一个好的选择。 This answer解释了为什么不应该使用AsyncTask。他们建议您使用更好的方法来处理长时间运行的任务,RoboSpice
我已经使用过这个库,我觉得值得尝试:尊重活动生命周期(方向改变),没有内存泄漏,支持多线程,缓存结果......它可以插拔长插请求任务使用缓存(但它不适用于非缓存请求)。

但我建议Google推出一个好方法:IntentServiceBroadcastReceiver。您将在方向更改期间注册和未注册广播以接收数据结果。所有后台任务都将在IntentService中工作,并通过BroadcastReceiver通知您想要活动的任何内容。您可以尝试很多示例。这样的事情:http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/

<强>更新

  

嗨R4j,重点是我的申请很安静。我要做   并行网络呼叫数。你使用IntentService的方法是   好,但不适合复杂的场景

我不认为这是一个问题。您可以使用IntentService执行任何操作,甚至是复杂的任务。如果您想要并行任务,您可以考虑使用多线程服务并通过Intent与活动进行通信。在服务和活动之间发送意图是安全和灵活的,这是Android方式。
如果你想缓存(通过文件下载,流,按数据库..)RoboSpice是你的最佳选择

答案 5 :(得分:-3)

您可以尝试以下方法:

1)如果您的应用程序显式要求更改方向,只需在应用程序执行开始时禁用方向更改,这样您就可以避免任何与方向更改相关的崩溃或相关问题。

您可以在布局xml文件的最外层布局中使用以下行:

  android:orientation="vertical"

(用于设置垂直方向)

2)您可以使用Asynctask在线程执行开始时设置或保留以前的方向值,如下所示(仅语法示例):

  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

  getResources().getConfiguration().orientation