在 Android 中处理"blocking"长时间运行的操作



有一种常见的应用程序行为模式,即除非完成当前操作,否则无法执行下一步操作。一个很好的例子是身份验证:一旦你向应用程序提供了登录名和密码,并点击"登录",应用程序就会屏蔽一段时间,向你显示一种"等等,我在工作"的指示。尽管这个任务很常见,但我没能在谷歌上找到一个"典型"的解决方案。

我牢记的要点:

  1. 绝对不能保证"活动"的使用寿命。活动保证在用户启动时启动,但它们可能随时被杀死。因此,一般来说,活动应该被视为交互点,您的应用程序和用户可以在这里讨论他们的"欲望"。总是由用户开始讨论。

  2. 另一方面,还有服务,这些组件从不直接与用户对话。的服务寿命保证,所以它似乎是放置处理逻辑的正确位置。

因此,对于我在一开始描述的任务,可以公平地声明:

  1. 应该有一个登录活动
  2. 此活动应能够在4种模式下运行:
    • 清洁/刚启动/用户尚未按下按钮
    • 用户按下按钮,我们正在与web API对话——这是一项长期运行的任务,我们希望显示一种ProgressDialog
    • 我们设法与web API进行了交谈,它表示一切正常。在这里,我们可能会完成此活动,并开始更有用的活动-用户在启动应用程序时最初希望看到的活动
    • 要么我们没能和网络API对话,要么它说用户凭据有问题。在这种情况下,我们将显示一条错误消息
  3. 应该有服务负责与网络API对话

所以,这里有一个问题:

如何正确地让"活动"知道当前应激活4种模式中的哪一种

我所考虑的:

  1. Activity+AsyncTask。根本不起作用,因为AsyncTask绑定到特定的Activity实例,并且一旦重新创建Activity(设备方向更改就是一个例子),AsyncTask就会绑定到"错误"的上下文。

  2. Activity+IntentService。活动触发服务并在Intent中提供"请求上下文"。一旦IntentService完成,它就使用sendBroadcast()来告诉Activity我们在哪里。这不起作用,因为当IntentService完成时,Activity已经可以暂停,所以它不会收到更新。

  3. 与第2页相同,但使用sendStickyBroadcast()。这解决了错过更新的问题,但谷歌表示,这是一种糟糕的做法,因为有些开销太大。

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

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

首先,如果你考虑到了你提到的所有要点,那么你肯定走在了"正确的方向"上。

您所描述的问题是非常常见的,并且与大多数应用程序有关

你的一些假设有问题:

活动+异步任务。根本不起作用,因为AsyncTask绑定到特定的"活动"实例,并且一旦重新创建"活动"(设备方向更改就是一个例子),AsyncTask就会绑定到"错误"的上下文。

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

使用androidService派生类中的AsyncTask(而不是IntentService.)也是一种很好的做法。这是可能的,因为CCD_ 28方法是从主线程执行的。

事实上,这是我认为的首选解决方案。

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

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

相反,您可以持久地/静态地遍历这个信息singelton类,当这个活动恢复时,它会将其检索回来,并显示相关的状态。

相关内容

  • 没有找到相关文章

最新更新