【发布时间】:2014-01-16 08:06:51
【问题描述】:
有一种常见的应用程序行为模式,即除非当前操作完成,否则您无法进行下一步。一个很好的例子是身份验证:一旦您向应用程序提供了登录名和密码,然后点击“登录”,该应用程序将阻止一段时间,向您显示一种“等等,我正在工作”指示符。即使这个任务很常见,我也没有设法在谷歌上找到一个“典型”的解决方案。
我牢记的要点:
绝对不能保证 Activity 的生命周期。活动保证在用户启动它们时启动,但是它们可以随时被终止。因此,一般而言,应将活动视为交互点,您的应用程序和用户可以在其中讨论他们的“愿望”。 始终由用户开始讨论。
另一方面,有一些服务,即从不直接与用户对话的组件。 有服务生命周期保证,因此它似乎是放置处理逻辑的正确位置。
所以,对于我一开始描述的任务,公平地说:
- 应该有一个登录活动。
- 此活动应该能够以 4 种模式运行:
- 清理/刚刚开始/用户尚未按下按钮。
- 用户刚刚按下按钮,我们正在与 Web API 对话 - 这是长期运行的任务,我们希望显示一种 ProgressDialog。
- 我们设法与 Web API 对话,它说一切正常。在这里,我们可能会完成这项活动并开始一项更有用的活动 - 用户在启动应用时最初希望看到的活动。
- 要么我们没有设法与 Web API 对话,要么它说用户凭据有问题。在这种情况下,我们会显示一条错误消息。
- 应该有 Service 负责与 Web API 对话。
所以,这里有一个问题:
我如何正确地让 Activity 知道 4 种模式中的哪一种当前应该处于活动状态?
我所考虑的:
-
Activity+AsyncTask。根本不起作用,因为AsyncTask绑定到特定的Activity实例,并且一旦重新创建Activity(例如设备方向更改),AsyncTask就绑定到“错误”上下文。 Activity+IntentService。 Activity 触发服务并在Intent中提供“请求上下文”。一旦IntentService完成,它使用sendBroadcast()告诉Activity我们在哪里。这不起作用,因为在IntentService完成时,Activity已经可以暂停,因此它不会收到更新。与第 2 页相同,但使用
sendStickyBroadcast()。这解决了错过更新的问题,但谷歌表示这是一种不好的做法,因为有一些开销之王或其他原因。使用
IntentService+ContentProvider+Loader。 Activity 触发服务并在Intent中提供“请求上下文”。请求上下文有一个神奇的“请求令牌”。该令牌描述了“做某事的独特意图”,因此当“某事完成”时,可以分辨出它是什么以及谁想要它。IntentService通过将请求记录保存到数据库开始处理:即请求令牌和状态(已启动)。然后它开始处理。处理完成后,它将记录状态更新为“完成”并将结果放在那里。同时,Activity使用Loader来收听这张唱片。它根据状态了解它应该在哪种模式下运行。此解决方案适用于所有场景,包括设备方向更改、离开活动、来电等,但感觉就像是奇怪的矫枉过正。
我想知道是否有更简单的解决方案。
【问题讨论】:
标签: android android-intent android-activity intentservice long-running-processes