假设我们正在开发一个消息传递应用程序,我们希望将消息发送到给定的对话中,其中这些消息的顺序仅在该对话中很重要,并且如果该应用程序被置于后台,我们希望保证消息将被发送。
WorkManager#beginUniqueWork 方法似乎很适合这个,其中 uniqueWorkName 将是一些对话 ID,并且将使用 ExistingWorkPolicy.APPEND作为工作方针,使工作按计划进行。
到目前为止,在我的应用程序中,只要每个 Work 都返回 Result.SUCCESS,那么任何 future 预定的工作都会按预期执行。但是,如果一个特定的消息无法以致命的方式发送并且我返回 Result.FAILURE,那么所有使用相同对话 ID 的 future 工作似乎永远不会到达我的 Worker#doWork( )。
在深入研究了EnqueueRunnable 类的源代码之后,这似乎是一个深思熟虑的选择。我无法真正理解的是为什么会这样?奇怪的是,如果 uniqueWorkName 失败,该名称将在应用程序的剩余生命周期内变得不可用(这在终止应用程序后仍然存在)。
此外,我想知道是否有人对此有好的解决方案,或者知道这是否会在 WorkManager 的 future 版本中发生变化。到目前为止,我能想到的最好的事情是返回 Result.SUCCESS 但在输出 Data 中编码我自己的失败状态,这样工作的任何观察者都知道它有失败的。然而,这有点尴尬,并且对于代码的 future 维护者来说不是很明显(并且在查看给定的 Work fragment 的日志时可能会有点困惑)。
也许我对独特作品的预期用途是完全错误的,并且有更好的解决方案。任何想法将不胜感激,谢谢!
最佳答案
所以我在 this google issue tracker report 中找到了我自己问题的答案.
基本上,使用 APPEND 策略的独特工作会创建一个 WorkContinuation,其中每个新项目都被链接起来,就好像我们要使用 WorkContinuation#then方法。失败或取消链会取消所有下游工作,因此这是预期的行为。
工单建议了两种方法:
If you really want APPEND's behavior, then another thing you could do is to check for WorkStatuses of the WorkRequests, and if (all of them happened to be cancelled) use REPLACE instead of APPEND. Bear in mind, this is inherently racy, because your WorkRequests might not have cancelled yet. So make sure you have some synchronization primitives around your use of WorkManager's APIs.
和
The simplest way to do this is to not actually return Result.FAILED; if you always return SUCCEEDED and return the actual pass/fail bit (if needed) in the output data, you can make sure the chain always keeps running.
这就是我已经在做的事情。希望这对其他人有帮助。
关于android - 工作管理器 : Why does failed unique work with the "APPEND" ExistingWork strategy not allow more work under the same name?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53033833/