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

3
有一种常见的应用程序行为模式,即除非当前操作完成,否则无法进行下一步。一个很好的例子是身份验证:一旦您提供了登录名和密码,并点击“登录”,应用程序会阻塞一段时间,显示一种“等待,我正在工作”的指示器。尽管这个任务非常普遍,但我没有找到一个“典型”的解决方案。
我牢记的主要要点如下:
1. Activity 的生命周期没有任何保证。当用户启动它们时,Activity 保证被启动,但之后它们可以在任何时刻被杀死。因此,通常应该将 Activity 视为应用程序和用户可以讨论其“愿望”的“交互点”。始终由用户开始这个讨论。
2. 另一方面,有 Service,这些组件从不直接与用户交互。Service 的生命周期有保证,因此似乎是放置处理逻辑的正确位置。
因此,对于我在最开始描述的任务,公正地说:
1. 应该有一个登录活动。
2. 这个活动应该能够以4种模式运行:
- 清洁/刚开始/用户还没有按按钮。 - 用户刚刚按下按钮,我们正在与 Web API 交谈 - 这是长时间运行的任务,我们想显示一种 ProgressDialog。 - 我们设法与 Web API 交谈,并且它说一切都很好。在这里,我们可能会完成此活动并开始更有用的活动 - 用户最初想看到的活动。 - 我们没有设法与 Web API 交谈,或者它说用户凭据有问题。在这种情况下,我们正在显示错误消息。
3. 应该有一个负责与 Web API 交谈的 Service。
因此,这里有一个问题:
如何正确使 Activity 知道当前应处于哪个4种模式?
我考虑过的:
  1. 使用Activity+AsyncTask,由于AsyncTask绑定特定的Activity实例,一旦Activity重新创建(例如设备方向更改),AsyncTask就会绑定到“错误”的上下文中,因此无法正常工作。

  2. 使用Activity+IntentServiceActivity触发服务并在Intent中提供“请求上下文”。一旦IntentService完成,它使用sendBroadcast()告诉Activity当前进度。但是由于当IntentService完成时,Activity可能已经暂停,因此它将无法接收更新。

  3. 与第二种情况类似,但使用sendStickyBroadcast()。这解决了丢失更新的问题,但Google认为这是一种不好的做法,因为会导致某种开销或其他问题。

  4. 使用IntentService+ContentProvider+LoaderActivity触发服务并在Intent中提供“请求上下文”。请求上下文具有一个神奇的“请求令牌”,该令牌描述了“唯一的意图”,因此当“某事被完成”时,可以知道它是什么以及谁想要它。 IntentService通过将请求记录保存到数据库中(即请求令牌和状态(已开始)),然后开始处理来开始处理。处理完成后,它会将记录状态更新为“已完成”并在其中放置结果。同时,Activity使用Loader监听此记录。根据状态,它了解应以哪种模式运行。这种解决方案对所有情况都完美地工作,包括设备方向更改、离开活动、接听电话等,但感觉有点过度。

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

1个回答

2
首先,如果您考虑到了您提到的所有点,那么您肯定是在“正确的方向”上。
您描述的问题非常普遍,并涉及大多数应用程序。
您的一些假设存在问题:
Activity + AsyncTask。由于AsyncTask绑定到特定的Activity实例,一旦Activity重新创建(例如设备方向更改),AsyncTask就会绑定到“错误”的上下文中,因此根本不起作用。
没有人说AsyncTask必须从Activity执行!
从android Service派生类(而不是IntentService)使用AsyncTask也是一个好习惯。这是可能的,因为Service方法是从主线程执行的。
实际上,我认为这是首选解决方案。
Activity + IntentService。 Activity触发服务并在Intent中提供“请求上下文”。一旦IntentService完成,它使用sendBroadcast()告诉Activity我们所在的位置。这不起作用,因为在IntentService完成时,Activity可能已经暂停,因此它将无法接收更新。
如果activity已经暂停/销毁-您没有任何理由更新它!!!
相反,您可以将此信息持久存储/静态单例类,当此activity恢复时,它将检索它并显示相关状态。

如果活动已经被销毁,则“暂停”意味着“暂停”,因此可以恢复 :-) - Andrey Agibalov
@loki2302: 好的,仍然是相同的解决方案-检查状态何时恢复为相同/其他实例。我已经更新了我的答案。 - Tal Kanel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接