处理方向更改的最佳实践:Android

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

  1. 附加 – 分离模型:附加和分离活动的线程和AsyncTask,同时保留他们的实例。 (来源: 1,2 )

  2. 无头片段方式:使用非UI /无头片段完成所有与线程有关的操作,并在configuration更改时保留其实例。 (来源: 1,2 )

有没有其他方法来处理这种情况? 什么是推荐的做法? 我问这是因为我找不到Android文档中的任何地方的通用解决scheme。

Solutions Collecting From Web of "处理方向更改的最佳实践:Android"

一些摘要

上面提到的几种方法都是很好的做法,但是我想我可以用简短的解释来总结它们。 以下是目前用于httpnetworking,asynchronous工作/线程和caching的一些最stream行的库。

我目前的项目(只是喜好)

我个人目前正在使用OttoLoadersVolleyOrmlite和基于ApacheService的networking堆栈。 我希望能够用VolleyRetrofit ,也许最终Robospicereplacenetworking堆栈。

个人非常喜欢奥托和沃利


RoboSpice(模块化)

  • https://github.com/octo-online/robospice
  • http://www.youtube.com/watch?v=ONaD1mB8r-A
  • 一个插件/模块化的方法长期运行的任务
  • 这就像图书馆的“瑞士军刀”,但你需要知道每个工具的作用。
  • 处理REST调用
  • 通过定位和其他更改来保持数据
  • 可以处理磁盘和内存caching)
  • 与各种HTTP库和持久性库(Gson,Jackson,Spring, OkHttp和许多下面的库)
  • testingOrmlite支持,我想

改造(REST)

Volley(networking数据和图像)

毕加索(图片)

装载机(Android)

  • 很好的支持
  • 坚持定向改变,保存/加载片段状态
  • 可能很难得到正确的
  • 没有caching

AsyncTask(Android)

  • 从UI线程进行后台工作的简单方法
  • 必须取消,并注意活动或碎片拆除后返回的任务。

奥托(活动巴士)

  • https://github.com/square/otto
  • 事件总线,使组件和碎片之间的同步工作很容易
  • 非常强大的@Produce能力保留了最后一个事件,并且可以根据需要为任何新的感兴趣的订户订购

无头碎片(?)

  • 我个人从来没有见过Vogella的教程,所以我不确定这个。

服务(Android)

  • 老派的方式
  • 终极控制,你必须自己做一切
  • 通常与Appache或HURL客户端和
  • 通过意图传递包裹

你为什么不尝试Loaders ,特别是AsyncTaskLoader ? 它们可以通过Support Library提供给Honeycomb,并完美匹配Activity / Fragment的生命周期。 这里是官方总结:

  • 他们可用于每个活动和片段。
  • 它们提供asynchronous的数据加载。
  • 他们监视数据的来源,并在内容发生变化时提供新的结果。
  • 它们在configuration更改后重新创build时会自动重新连接到最后一个加载器的光标。 因此,他们不需要重新查询他们的数据。

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

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

所以,如果我不得不推荐的东西将是下一件事情:

活动pipe理API调用和stream(使用RoboSpice,让用户界面旋转)使用retainInstance为true的片段内的简单屏幕。 这让你把你的DTO直接传递给你的片段,而且你只需要pipe理顶层Activity的状态。

如果处理asyncTask是你主要关心的问题,也就是说每次方向改变都不愿意下载数据,那么你可以尝试这样 –

(1)像这样创build之前初始化任何值。

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

希望能帮助到你 ..

有许多方法可以尝试旁边的AsyncTask。 如果你试图find一个最佳的做法,AsyncTask不是一个好的select。 这个答案解释了为什么你不应该使用AsyncTask。 而且他们推荐你使用一个更好的方式来处理长时间运行的任务, RoboSpice 。
我已经使用这个库,我认为这是值得的尝试:尊重活动的生命周期(方向改变),没有内存泄漏,支持multithreading,caching结果…它可以通过使用caching插入和拔出长的请求任务(但对于非caching请求,它不能很好地工作)。

但是我推荐一个来自Google的好方法: IntentServiceBroadcastReceiver 。 在方向变更过程中,您将注册和取消注册广播,以接收数据结果。 所有后台任务将在IntentService中工作,并通过BroadcastReceiver通知任何您想要的活动。 有很多例子,你可以尝试。 像这样的东西: http : //mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/

更新

嗨R4j,重点是我的应用程序是安静复杂的。 而且我必须做一些并行的networking通话。 IntentService的方法很好,但不适用于复杂的场景

我不认为这是一个问题。 IntentService可以做任何事情,甚至是复杂的任务。 如果你想要并行任务,你可以考虑一个带有multithreading的服务,并通过Intent与活动进行通信。 发送服务和活动之间的意图是安全和灵活的,这是Android的方式。
如果你想caching(通过文件下载,stream,数据库..) RoboSpice是您的最佳select

您可以尝试以下方法:

1)如果您的应用程序没有明确要求任何方向更改,只需在应用程序执行开始时禁用方向更改,从而避免任何方向更改的崩溃或相关问题。

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

  android:orientation="vertical" 

(用于设置垂直方向)

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

  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

  getResources().getConfiguration().orientation