在Android中处理“阻止”长时间运行的操作

时间:2014-01-16 08:06:52

标签: android android-intent android-activity intentservice long-running-processes

有一种常见的应用程序行为模式,除非当前操作完成,否则无法进入下一步。一个很好的例子是身份验证:一旦您为应用程序提供了登录名和密码,并点击了“登录”,该应用程序将阻止一段时间显示您的“等待,我正在工作”指示器。虽然这项任务很常见,但我没有设法谷歌成为“典型”的解决方案。

我记住的要点:

  1. 绝对不保证活动生命周期。保证在用户启动活动时启动活动,但随后可以随时杀死它们。因此,一般来说,活动应该被视为交互点,您的应用和用户可以在其中讨论他们的“愿望”。 始终由用户开始讨论。

  2. 另一方面,有服务,组件从不直接与用户交谈。 保证服务生命周期,因此它似乎是处理逻辑的正确位置。

  3. 所以,对于我刚开始描述的任务,可以说:

    1. 应该有登录活动。
    2. 此活动应该能够以4种模式运行:
      • 清洁/刚开始/用户没有按下按钮。
      • 用户刚按下按钮,我们正在与Web API交谈 - 这是一项长期运行的任务,我们希望显示一种ProgressDialog。
      • 我们设法与Web API交谈,它说一切都很好。在这里,我们可能会完成此活动并启动更有用的活动 - 用户最初想要看到的活动,当他们推出应用时。
      • 要么我们没有设法与Web API交谈,要么说用户凭据有问题。在这种情况下,我们显示错误消息。
    3. 应该有服务负责与Web API交谈。
    4. 所以,这是一个问题:

      如何正确地让活动知道4种模式中的哪一种当前应该处于活动状态?

      我考虑过:

      1. Activity + AsyncTask。完全不起作用,因为AsyncTask绑定到特定的Activity实例,并且一旦Activity被重新创建(设备方向更改就是一个示例),AsyncTask必然会“错误” “上下文。

      2. Activity + IntentService。 Activity触发服务并在Intent中提供“请求上下文”。完成IntentService后,会使用sendBroadcast()告诉Activity我们在哪里。这不起作用,因为在IntentService完成的那一刻,Activity已经暂停,因此它不会收到更新。

      3. 与p.2相同,但使用sendStickyBroadcast()。这解决了错过的更新问题,但谷歌表示这是一个不好的做法,因为有一些开销之王或其他什么。

      4. 使用IntentService + ContentProvider + Loader。 Activity触发服务并在Intent中提供“请求上下文”。请求上下文具有神奇的“请求令牌”。这个标记描述了“做某事的独特意图”,因此当“完成某事”时,可以告诉它是什么以及谁想要它。 IntentService通过将请求记录保存到数据库来开始处理:即请求令牌和状态(已启动)。然后它开始处理。处理完成后,它会将记录状态更新为“完成”并将结果放在那里。同时,Activity使用Loader来收听此记录。它根据状态了解它应该运行的模式。此解决方案适用于所有场景,包括设备方向更改,离开活动,来电等,但感觉就像奇怪的过度杀伤

      5. 我想知道是否有更简单的解决方案。

1 个答案:

答案 0 :(得分:2)

首先,如果你记住你提到的所有要点,你肯定是在“正确的方向”。

您描述的问题非常常见,并且涉及大多数应用程序

你的一些假设存在问题:

  

活动+ AsyncTask。完全不起作用,因为AsyncTask绑定到特定的Activity实例,并且一旦重新创建了Activity(设备方向更改就是一个例子),AsyncTask被绑定到“错误”的上下文。

没有人说AsyncTask必须从Activity执行!!

使用来自android AsyncTask派生类(不是Service ..)的IntentService也是一种很好的做法。这是可能的,因为Service方法是从主线程执行的。

实际上,这是我相信的首选解决方案。

  

活动+ IntentService。 Activity触发服务并在Intent中提供“请求上下文”。完成IntentService后,它使用sendBroadcast()告诉Activity我们在哪里。这不起作用,因为当IntentService完成时,Activity已经暂停,因此它不会收到更新。

如果活动已暂停/销毁 - 您无论如何都没有任何理由更新!!!!!

相反,你可以坚持不懈地追踪这些信息/静态singeltone类,并且当这个活动恢复时 - 它会将其恢复,并显示相关状态。