如何将“goAsync”用于广播接收器?
Posted
技术标签:
【中文标题】如何将“goAsync”用于广播接收器?【英文标题】:How to use "goAsync" for broadcastReceiver? 【发布时间】:2014-05-09 14:08:58 【问题描述】:背景
从 Honeycomb (API 11) 开始,android 具有允许广播接收器以异步方式运行的功能,在假定它可以终止其进程之前提供大约 10 秒,使用称为“goAsync”的方法:
这可以由 onReceive(Context, Intent) 中的应用程序调用以 允许它在从那个返回后保持广播活动 功能。这并没有改变相对的期望 响应广播(在 10 秒内完成),但允许 将与之相关的工作转移到另一个线程的实现 以避免由于磁盘 IO 而导致主 UI 线程出现故障。
问题
我搜索了很多地方,没有找到任何使用方法的示例或教程。
不仅如此,该方法还返回一个 PendingIntent 实例,我不确定如何处理它:
返回一个表示结果的 BroadcastReceiver.PendingResult 活跃的广播。 BroadcastRecord 本身不再活跃; 所有数据和其他交互都必须经过 BroadcastReceiver.PendingResult API。 PendingResult.finish() 广播处理完成后必须调用方法。
问题
您如何使用这种方法?
它返回的PendingIntent是什么,我该怎么处理?
【问题讨论】:
【参考方案1】:你可以找到简短的解释here。
如果您想将BroadcastReceiver
的onReceive()
方法内部的处理移交给另一个线程,请使用goAsync()
。然后可以在那里完成onReceive()
方法。 PendingResult 被传递给新线程,您必须调用PendingResult.finish()
来实际通知系统此接收器可以回收。
例如:
final PendingResult result = goAsync();
Thread thread = new Thread()
public void run()
int i;
// Do processing
result.setResultCode(i);
result.finish();
;
thread.start();
【讨论】:
从onReceive方法返回的总时间为10秒。这意味着您的线程最多可以运行 10 秒减去您在启动线程之前在 onReceive 方法中花费的时间。没有尝试过代码,因为它在那里 setResult 不是必需的,它仅用于在有序广播期间在接收器之间传递数据。你可以忽略它。 我不明白 setResultCode 的用途以及如何使用它。你将如何传递它?另外,您是否尝试过此代码? 一个有序的广播按顺序通过每个注册的广播接收器。顺序由意图过滤器的优先级属性定义。然后,每个接收器都可以使用 setResult() 之类的方法将数据传递给下一个接收器,甚至完全停止广播。行动。 ACTION_NEW_OUTGOING_CALL 是一个有序广播。您可以使用 setResult 修改额外的 EXTRA_PHONE_NUMBER,这将更改将要拨打的电话号码。 setResult 方法接受一个 int、String 和一个 Bundle。如果是电话号码,您可以通过这种方式传递包含电话号码的捆绑包。不过,这与原始问题的主题非常偏离。问题是关于如何使用 goAsync,而不是关于 BroadcastReceiver 一般如何工作。如果该部分已回答,请标记为已解决。【参考方案2】:在kotlin中你可以在BroadcastReceiver上写一个扩展函数:
/**
* Run work asynchronously from a [BroadcastReceiver].
*/
fun BroadcastReceiver.goAsync(
coroutineScope: CoroutineScope,
dispatcher: CoroutineDispatcher,
block: suspend () -> Unit
)
val pendingResult = goAsync()
coroutineScope.launch(dispatcher)
block()
pendingResult.finish()
在您的广播接收器中之后,您可以执行以下操作:
class AlarmBroadcastReceiver : BroadcastReceiver()
override fun onReceive(context: Context, intent: Intent)
// Code here runs on the main thread
goAsync(GlobalScope, Dispatchers.Default)
// The code here will run on the background by the default dispatcher on the global scope
// If your code here touches the IO, then you can use Dispatchers.IO instead
【讨论】:
为什么需要参数?它总是相同的参数。相反,它应该只有在那里做什么的参数。另外,我认为您不应该在这里使用协程。如果它的线程池中有一些线程正在被使用,它会先等待它们完成。 对于参数,也许你有一个托管协程范围,你想在这种情况下使用。不推荐使用全局范围,因为它不支持结构化并发。使用协程简化了代码,您可以立即执行代码,而无需使用特定的调度程序等待。 原来你写了代码,现在又说不推荐使用? 我建议将块包装在try finally
中,以确保最后始终调用 finish()
。
只是给未来的谷歌人的一个提示,Ian Lake 在 Muzei 应用程序中将其与 GlobalScope
一起使用,所以我认为它可能没问题 github.com/muzei/muzei/blob/…以上是关于如何将“goAsync”用于广播接收器?的主要内容,如果未能解决你的问题,请参考以下文章