小编Gui*_*rgy的帖子

WorkManager 在工作完成后保留通知

我想在工作人员在后台运行时显示通知。我可以用下面的代码来做到这一点:

override suspend fun doWork(): Result {
    val manager = NotificationManagerCompat.from(applicationContext)
    val channel = "some_channel"
    val id = 15
    val builder = NotificationCompat.Builder(applicationContext, channel)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        manager.createNotificationChannel(NotificationChannel(channel, "DefaultName", NotificationManager.IMPORTANCE_LOW))

    builder
        .setOnlyAlertOnce(true)
        .setOngoing(true)
        .setAutoCancel(false)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setSmallIcon(android.R.drawable.ic_dialog_alert)
        .setTicker("Background Task")
        .setContentText("Starting")
        .setProgress(0, 0, true)

    setForeground(ForegroundInfo(id, builder.build()))

    delay(500)

    manager.notify(id, builder.setContentText("Progress A").setProgress(20, 0, false).build())
    for (i in 1..20) {
        delay(100)
        manager.notify(id, builder.setProgress(20, i, false).build())
    }

    delay(500)

    manager.notify(id, builder.setContentText("Progress B").setProgress(2, 0, false).build())
    delay(1000)
    manager.notify(id, builder.setProgress(2, 1, false).build())
    delay(1000)
    manager.notify(id, builder.setProgress(2, 2, false).build())

    delay(1000)

    manager.notify(id, …
Run Code Online (Sandbox Code Playgroud)

android android-notifications android-workmanager

6
推荐指数
1
解决办法
2838
查看次数

消耗 System.Threading.Channels.Channel 中的所有消息

假设我有很多生产者,1个消费者未绑定 Channel,有一个消费者:

await foreach (var message in channel.Reader.ReadAllAsync(cts.Token))
{
    await consume(message);
}
Run Code Online (Sandbox Code Playgroud)

问题在于该consume函数会进行一些 IO 访问,并且可能还会进行一些网络访问,因此在消耗 1 条消息之前可能会产生更多消息。但由于IO资源不能并发访问,所以我不能有很多消费者,也不能把函数扔到consume一个Task中然后忘记它。

consume功能可以轻松修改以获取多条消息并批量处理它们。所以我的问题是,是否有一种方法可以让消费者在尝试访问通道队列时获取通道队列中的所有消息,如下所示:

while (true) {
    Message[] messages = await channel.Reader.TakeAll();
    await consumeAll(messages);
}
Run Code Online (Sandbox Code Playgroud)

编辑:我能想到的 1 个选项是:

List<Message> messages = new();
await foreach (var message in channel.Reader.ReadAllAsync(cts.Token))
{
    await consume(message);
    Message msg;
    while (channel.Reader.TryRead(out msg))
        messages.Add(msg);
    if (messages.Count > 0)
    {
        await consumeAll(messages);
        messages.Clear();
    }
}
Run Code Online (Sandbox Code Playgroud)

但我觉得这应该是一个更好的方法来做到这一点。

c# channel producer-consumer system.threading.channels

4
推荐指数
1
解决办法
3727
查看次数