mirror of https://github.com/tasks/tasks
Throttle all notify/cancel notification mgr calls
parent
5624816cac
commit
3936c221ae
@ -1,33 +1,37 @@
|
||||
package org.tasks.notifications
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.tasks.time.DateTimeUtils.currentTimeMillis
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors.newSingleThreadExecutor
|
||||
|
||||
internal class Throttle constructor(
|
||||
ratePerPeriod: Int,
|
||||
private val periodMillis: Long = 1000,
|
||||
private val tag: String = "",
|
||||
private val scope: CoroutineScope =
|
||||
CoroutineScope(newSingleThreadExecutor().asCoroutineDispatcher() + SupervisorJob()),
|
||||
private val sleeper: suspend (Long) -> Unit = { delay(it) }) {
|
||||
private val executor: Executor = newSingleThreadExecutor(),
|
||||
private val sleeper: (Long) -> Unit = { Thread.sleep(it) }) {
|
||||
private val throttle: LongArray = LongArray(ratePerPeriod)
|
||||
private var oldest = 0
|
||||
|
||||
@Synchronized
|
||||
fun run(runnable: suspend () -> Unit): Job = scope.launch {
|
||||
val sleep = throttle[oldest] - (currentTimeMillis() - periodMillis)
|
||||
if (sleep > 0) {
|
||||
Timber.v("$tag: Throttled for ${sleep}ms")
|
||||
sleeper.invoke(sleep)
|
||||
fun run(runnable: suspend () -> Unit) {
|
||||
executor.execute {
|
||||
val sleep = throttle[oldest] - (currentTimeMillis() - periodMillis)
|
||||
if (sleep > 0) {
|
||||
Timber.v("$tag: Throttled for ${sleep}ms")
|
||||
sleeper.invoke(sleep)
|
||||
}
|
||||
try {
|
||||
runBlocking {
|
||||
runnable.invoke()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
throttle[oldest] = currentTimeMillis()
|
||||
oldest = (oldest + 1) % throttle.size
|
||||
}
|
||||
try {
|
||||
runnable.invoke()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
throttle[oldest] = currentTimeMillis()
|
||||
oldest = (oldest + 1) % throttle.size
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package org.tasks.notifications
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.Context
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import java.util.concurrent.Executors.newSingleThreadExecutor
|
||||
import javax.inject.Inject
|
||||
|
||||
class ThrottledNotificationManager @Inject constructor(
|
||||
@ApplicationContext val context: Context
|
||||
) {
|
||||
private val notificationManagerCompat = NotificationManagerCompat.from(context)
|
||||
private val executor = newSingleThreadExecutor()
|
||||
private val throttle = Throttle(NOTIFICATIONS_PER_SECOND, executor = executor, tag = "NOTIFY")
|
||||
|
||||
fun cancel(id: Int) {
|
||||
executor.execute {
|
||||
notificationManagerCompat.cancel(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun notify(id: Int, notification: Notification) {
|
||||
throttle.run {
|
||||
notificationManagerCompat.notify(id, notification)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NOTIFICATIONS_PER_SECOND = 4
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue