android – 好设计:工作线程和活动重启

众所周知,Android将我们的应用程序组件(活动,服务)置于任何时刻被杀害的威胁之下.如果您想提供一个强大的,无泄漏的解决方案,同时保持代码清洁并解决关注点分离,这会使事情变得非常复杂.

问题:
活动开始一个耗时的任务(以Runnable,AsyncTask或其他任何机制的形式).应显示进度对话框.该任务将打开几个连接,但它应该有一个更新进度条的方法,它可能需要显示一个选择对话框中途完成.它还应该能够关闭对话框并在发生错误或完成时显示Toast.

一个Activity被杀死,稍后重新创建一个新实例时,我可以想到两个选项:

>尝试同时终止正在运行的任务,并在创建新的替代活动实例时生成一个任务实例.对于长时间运行的任务,这不是一个选项,因为从用户的角度来看,启动任务并看到进度条指示器从80%回到0%是不可接受的,没有明显的原因.然而,这是Shelves example by Romain Guy中采用的方法.显然,这是官方开发人员指南中推荐的方法.
>保持任务运行:因此我们可以订阅(并可能启动)onResume上的更新任务,并在onPause取消订阅(并可能暂停)它.

在第二个选项之后意味着我们应该防止在活动被暂时销毁的情况下收集任务.例如,我们可以在一个自定义的Application类中声明它,或者甚至将它作为服务提供给应用程序的其余部分(使用Singleton?一个Android服务?)我不喜欢这个,但是,因为任务是仅由活动使用,因此将其提供给其他类是没有意义的.另一方面,Android Services也必须处理生命周期.

选项#2还涉及确保旧活动不会泄露.如果没有活动,我们不应该尝试更新GUI.整个想法应该是线程安全的.最后,在我们确定不再需要任务之后,任务不应该留在内存中.但与此同时,如果初始活动被破坏,任务继续运行,并且新的替代活动启动,则任务必须立即更新GUI并显示任务当前状态(或者结果是否完成).

当没有显示任何活动时,任务可能正在运行这一事实是另一个需要处理的问题,因为我们可能需要在某个时刻同步进行用户交互(选择对话框).如果活动能够在到达onPause时立即暂停任务,则可以解决此问题,但是任务可能需要一些时间来暂停或甚至无法执行此操作.

我之前已经问过类似的问题,但我并没有具体询问如何解决问题,而是提出了为了实现松散耦合而建议采用何种设计,并尽可能地将活动与任务隔离开来.

简而言之:
– 这是Android开发中反复出现的问题,之前有人可能会想出一个聪明的设计.是否有设计模式或经过良好测试的库可以简化这一过程?
– 如果你要实现#2,你会选择哪个类来完成任务(Runnable,Service等)以及它如何与活动进行通信?

附:请不要根据“orientation | keyboardHidden”hack XD发布解决方案.除此之外,任何帮助将不胜感激.

更新:
我的第一次尝试有点乱.该应用程序是一个蓝牙打印实用程序,涉及检测BT状态(并要求用户启用它,如果它被禁用),检索配对设备(并要求用户选择一个,如果有多个),然后发送数据最后告知用户结果.由于此任务是80%的IO代码,20%与GUI相关的操作,我不得不在任务的开始和结束时对GUI代码进行分组,然后将其从任务中移回活动.我有一个IntentService来完成繁重的工作,然后通过broadcastReceiver报告回活动.这解决了大多数问题,但这种设计存在一些问题.首先,所有那些常量字符串用作从输入和输出Intents中放入和检索字段的键,它们引入了语义耦合.我在活动< - >服务通信中更喜欢类型安全.而且我还必须解决如何将复杂的自定义对象传递给Intent中的服务,现在我已经遇到了Parcelables和原始参数.最后,活动和服务都使用相同的API(蓝牙),我更倾向于在单个类中使用与BT相关的代码.我想我会抛弃这个设计,并再次使用基于线程的自定义打印队列,尽管它会更难处理被杀死的活动.

解决方法

为什么不让您的活动启动服务来托管长时间运行的任务?服务是保持长期运营的最佳选择.您可以向操作系统提供提示以使其保持运行.见 startForeground()START_STICKY.

您可以通过从服务广播回复活​​动.让您的活动以编程方式注册broadcast receiver来监听这些意图.如果活动暂停,取消注册您的接收器,那么当您不在前台时,您将不会响应.

如果操作系统破坏了你的服务,那么它就会扼杀这个过程,所以无论如何你的任务都将失败.你能做的最好就是重启它.无论如何,如果考虑上述情况,除非在极端条件下,否则不会发生这种情况.

编辑:总结评论中捕获的一些想法…保持长时间运行的工作程序并自动重新启动它几乎总是错误的做法.移动设备没有电源来实现这一点.作者说他有一个特殊的条件,否定了这个问题……只有当设备几乎总是连接到电源时才会这样.

android模型是为您的应用程序提供一组强大的意图(通知).当需要做某事时,这些意图会唤醒您的设备/应用程序.您的应用应该处理通知,然后让设备立即返回休眠状态.

如果没有映射到您的事件的库存意图,您可以使用Google Cloud Messaging从服务器唤醒设备.换句话说,让长时间运行的进程在服务器上运行,并在需要时唤醒设备.

如果你能做到这一点,另一种方法是使用AlarmManager定期唤醒并检查一些状态.即使你经常这样做(例如,每5分钟,这也是一个禁忌),它总是比保持设备清醒一样好于建议.另外,使用不精确的唤醒间隔(参见上面链接的文档).

相关文章

这篇“android轻量级无侵入式管理数据库自动升级组件怎么实现...
今天小编给大家分享一下Android实现自定义圆形进度条的常用方...
这篇文章主要讲解了“Android如何解决字符对齐问题”,文中的...
这篇文章主要介绍“Android岛屿数量算法怎么使用”的相关知识...
本篇内容主要讲解“Android如何开发MQTT协议的模型及通信”,...
本文小编为大家详细介绍“Android数据压缩的方法是什么”,内...