android - 如何在 Android 8.0 中正确更新小部件 - Oreo - API 26

标签 android multithreading widget background-process android-8.0-oreo

假设我有一个应用的小部件,它的 targetSDKVersion 设置为 26。这个小部件需要 100 毫秒到 10 秒才能更新。大部分时间都在 1s 以内。在 Android O 之前,如果在我的 AppWidgetProvider 上调用 onUpdate(),我可以启动一个后台服务来更新这个小部件。但是,如果您尝试该行为,Android O 会返回 IllegalStateException。启动前台服务的显而易见的解决方案似乎是一种极端措施,因为它可以在 99% 的时间内在 10 秒内完成。

可能的解决方案

  • 启动前台服务以更新小部件。用 10 秒后就会消失的通知来惹恼用户。
  • 使用 JobScheduler 尽快安排作业。您的小部件可能会在一段时间内更新,也可能不会更新。
  • 尝试在广播接收器中完成这项工作。锁定任何其他应用程序的 UI 线程。糟糕。
  • 尝试在小部件接收器中工作。锁定任何其他应用程序的 UI 线程。糟糕。
  • 滥用 GCM 来运行后台服务。工作量很大,感觉很老套。

我个人不喜欢上述任何解决方案。希望我错过了什么。

(更令人沮丧的是,我的应用程序已经被系统调用 onUpdate() 加载到内存中。我看不到如何将我的应用程序加载到内存中以调用 onUpdate(),但是却没有给我的应用程序 1 秒更新UI 线程外的小部件可以节省任何电池生命周期。)

最佳答案

您没有说明更新触发机制是什么。您似乎担心延迟(“您的小部件可能会或可能不会在一段时间内更新”),因此我假设您的担心与用户与应用小部件的交互有关,例如点击按钮。

Use JobScheduler to schedule a job as quickly as possible. Your widget may or may not get updated for a while.

这是“使用 JobIntentService”的变体,AFAIK 是此类场景的推荐解决方案。

其他选项包括:

  • getForegroundService()PendingIntent 一起使用。有了这个,您有效地“发誓”您的服务将在 ANR 时间范围内调用 startForeground()。如果工作时间超过几秒钟,请调用 startForeground() 以确保 Android 不会胡思乱想。这应该最大限度地减少前台通知出现的次数。而且,如果用户点击了一个按钮,而几秒钟后您仍在忙于工作,您可能想要显示通知或以其他方式让用户知道他们要求的内容仍然存在进行中。

  • BroadcastReceiver 上使用 goAsync(),在接收器的上下文中执行工作,同时不占用主应用程序线程。我没有在 Android 8.0+ 上尝试过这个,所以 YMMV。

关于android - 如何在 Android 8.0 中正确更新小部件 - Oreo - API 26,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46179256/

相关文章:

java - 在 Android 中更改 TextView 的值

java - 检查 Android 中的子 Firebase 数据库中是否存在值

Android包括布局文件(引用id)

c++ - 使用 std::shared_ptr 在生产者/消费者线程之间共享数据

java - 当我们在应用程序日志中有线程名称时,如何识别线程启动的 Java 代码

c++ - 类的一部分互斥

html - 使用 Twitter 的新小部件时如何禁用消息 “Are you sure you want to send a form again”?

java - 首选项无法将 java.lang.boolean 转换为 String

android - 从 AsyncTask 更新两个独立的小部件

c++ - 从不同线程创建 QMainWindow