“处理”;“封锁”;Android中的长时间运行操作

“处理”;“封锁”;Android中的长时间运行操作,android,android-intent,android-activity,intentservice,long-running-processes,Android,Android Intent,Android Activity,Intentservice,Long Running Processes,有一种常见的应用程序行为模式,在当前操作未完成之前,无法执行下一步操作。一个很好的例子是身份验证:一旦你向应用程序提供了你的登录名和密码,并点击“登录”,应用程序将阻塞一段时间,同时向你显示一个类似“等待,我正在工作”的指示器。尽管这个任务很常见,但我并没有在谷歌上找到一个“典型”的解决方案 我记住的要点是: 绝对不能保证活动的生命周期。活动保证在用户启动时启动,但在任何时候都可能被终止。因此,一般来说,活动应该被视为互动点,在这里你的应用程序和用户可以讨论他们的“愿望”。开始讨论始终由用户决定

有一种常见的应用程序行为模式,在当前操作未完成之前,无法执行下一步操作。一个很好的例子是身份验证:一旦你向应用程序提供了你的登录名和密码,并点击“登录”,应用程序将阻塞一段时间,同时向你显示一个类似“等待,我正在工作”的指示器。尽管这个任务很常见,但我并没有在谷歌上找到一个“典型”的解决方案

我记住的要点是:

  • 绝对不能保证活动的生命周期。活动保证在用户启动时启动,但在任何时候都可能被终止。因此,一般来说,活动应该被视为互动点,在这里你的应用程序和用户可以讨论他们的“愿望”。开始讨论始终由用户决定

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

  • 因此,对于我在一开始描述的任务,公平地说:

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

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

    我所考虑的:

  • 活动
    +
    异步任务
    。由于
    异步任务
    绑定到特定的
    活动
    实例,并且一旦重新创建了
    活动
    (例如设备方向更改),
    异步任务
    绑定到“错误”上下文,因此根本不起作用

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

  • 与第2页相同,但使用
    sendStickyBroadcast()
    。这解决了错过更新的问题,但谷歌表示,这是一个糟糕的做法,因为有一些开销或其他原因

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


  • 我想知道是否有一个更简单的解决办法。

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

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

    您的一些假设存在问题:

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

    没有人说必须从
    活动执行
    AsyncTask

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

    事实上,这是我认为最好的解决方案

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

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


    相反,您只需持久地/静态地选择singeltone类,当此活动恢复时,它会将其检索回来,并显示相关状态。

    “如果活动已销毁”-“暂停”表示“暂停”,因此可以恢复:-)@loki2302:ok,仍然是相同的解决方案-检查相同/其他实例何时恢复状态。我已经更新了我的答案