【问题标题】:Update Activity data from service when its paused暂停时从服务更新活动数据
【发布时间】:2015-02-28 18:36:04
【问题描述】:

假设我有一个包含数据对象的活动。它根据该对象更新其 gui 组件。现在让我们说它已暂停(调用 OnPause)但没有停止或销毁

同时,收到推送通知(intentservice 已启动),我需要使用推送通知对象更新该对象,以便在应用程序恢复时更新我的​​ gui。

我曾考虑向活动发送广播,以便它可以更新其数据对象但我在某处读到,当活动暂停时,不会收到广播。

在这种情况下我该怎么办?

【问题讨论】:

    标签: android android-sqlite android-contentprovider android-lifecycle


    【解决方案1】:

    很难但正确的方法是为您的应用程序构建您自己的自定义ContentProvider,并更新从网络服务接收到的所有数据并将通知推送到此ContentProvider。当Activity 回到前台时,它会使用ContentProvider 提供的新数据进行自我更新。

    很难,因为制作自定义 ContentProvider 需要大量工作。这是正确的方式,因为它符合移动应用程序的行为和 Android 架构:假设用户激活 Web 服务或一些计算密集型任务,然后关闭应用程序;或者说推送通知到达并要求更新和显示应用程序的数据。在这两种情况下,应用程序的Activitys 可能不再位于前台,但Service 可用于执行一些非UI 操作。现在在该操作结束时,Service 通过ContentProvider 对数据进行更改,当用户再次激活应用程序时,Activitys 从ContentProvider 获取新数据。

    引用official tutorial:

    内容提供者是将数据连接在一起的标准接口 代码在另一个进程中运行的进程。

    作为开发人员,您应该始终假定用户可以随时调用应用并随时关闭它。无论Activity 是否在前台,都需要正确更新和维护应用程序的数据。

    Google 自己的应用使用自定义 ContentProviders。 Gmail 应用程序特别利用其ContentProvider 在网络连接可用时获取新电子邮件并离线显示电子邮件。 Facebook、WhatsApp 和 Twitter Android 应用程序也使用了ContentProviders。

    【讨论】:

    • 感谢您提供正确的行为。如果有教程您也可以指出我,我将不胜感激。 ContentProvider 在我看来就像共享首选项,您可以根据您的描述从服务或活动中调用它
    • @Snake:没有比official docs 更好的开始...顺便说一句,请参阅编辑后的答案。
    • OP 还应注意文档声明:“如果您不打算与其他应用程序共享数据,则无需开发自己的提供程序。”这是一个比基于问题所需的更复杂的答案......
    【解决方案2】:

    你几乎把它当作 Activity 被销毁了。您不能真正假设它不会在调用 onPause 后发生。

    如果对象表示持久的东西,那么只需更新对象的持久部分并在 Activity 恢复时检索它。例如,如果它代表服务的状态,则绑定到服务并更新。如果是数据库,则更新数据库,然后刷新Activity onResume。

    如果它是一个仅在 Activity 生命周期内有效的临时对象,那么您需要使某些东西持久化,以便 Activity 在恢复时可以检查。一些简单的东西,比如“sharepreferences”中的布尔变量。在 onResume 中,检查对象,如果存在,则检索对象,然后清除对象。

    【讨论】:

    • 我 +1 用于细分情况。在我的情况下,该对象仅在活动的生命周期内有效。我仍然不确定您的回答如何更新该临时对象
    【解决方案3】:

    我考虑向活动发送广播,以便它可以更新 它的数据对象但我在某处读到,当活动暂停时 没有收到广播。

    在这种情况下我该怎么办?

    我认为该信息的来源是不正确的,如果您在onCreate 中声明接收者并在onDestroy 中删除它,您不会有任何问题。我的意思是,首先使用您的服务解析推送通知,然后将localBroadcast 发送到活动。它就像你想象的那样简单。然后在 reciever 的 onRecieve 方法更新您的 GUI。

    【讨论】:

    • 嗯,它在 stackoverflow 上。那么在activity暂停的时候还是会收到广播?
    • 是的,broadcast 正在工作,您可以自己尝试 :-)。只需在发送广播之前使用例如SystemClock.sleep(4000); 并在收到通知后按主页按钮,因此现在您的活动已停止,4 秒后您的 UI 必须更新。所以再次启动你的活动来检查:-)。
    • 您可以将contentProvider 用于大型结构化数据,但如果您只想显示文本,我认为发送广播更容易且更准确,但如果您有大量结构化数据必须在应用程序的其他部分显示和使用的学生列表示例列表使用 database 和 contentProvider 和 loader
    • 感谢验证(加一)。我的结构更复杂,但我明白你的意思
    【解决方案4】:

    当Activity 启动时,您应该绑定到Service。然后在onResume 中,您可以请求在活动暂停时可能发生的更新。

    您可以考虑在 Activity 暂停时通过回调将数据传递给 Activity 以更新 Activity 中的变量,但随后您需要更新 onResume 中的 UI。

    还要考虑到当您的Activity 暂停时,它可能会被销毁并重新创建。根据您的问题,您似乎并不关心这种情况,但我认为解释它很重要。要处理此场景的任何更改,您需要保留更改的数据。如果您正在持久化数据,那么您不需要绑定到Service,您只需检查onResume 中的持久化数据存储。

    编辑:

    在您的评论中,您提到了您无法“绑定”到的 IntentService。在这种情况下,您有几个选项(基本上按优先顺序列出)。首先,您可以在创建活动时创建Service,然后让IntentService 将意图转发到该服务。其次,您可以在您的Activity 中有一个Static 变量以允许IntentService 访问共享数据存储。如前所述,您还可以持久化数据(放入SharedPreferences,文件或数据库。最后,您可以使用Application 类来存储对数据的引用,以便在您的应用程序处于活动状态时,您可以通过数据。

    【讨论】:

    • 我无法绑定到该服务,因为它是在收到 GCM 时产生的意图服务。 IntentService 将在活动生命周期内的某些时候运行
    • 这与标准服务不同。我编辑了我的答案。
    • +1 用于订购的解决方案。静态变量就像应用程序类,它是单例..对。所以不知道为什么申请会是最后一个
    • 静态变量类似于Application 类...但它的使用让开发人员试图以非预期或会导致其他问题的方式使用该类。对于大多数开发人员来说,处理静态变量比深入研究Application 类的优缺点更容易...... IMO
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    相关资源
    最近更新 更多