Android: 如何检测 workmanager 已经处于排队模式多长时间?
Android: How to detect how long workmanager is already in enqueue mode?
我想检测特定作品已经处于 enqueue
模式多长时间。我需要这些信息,以便通知用户他的状态(例如,当 workmanager 在 enqueue mode
中超过 10 秒时 -> 取消工作 -> 通知用户他需要做 X 以实现 Y)。像这样:
伪代码
workInfo.observe(viewLifecylceOwner) {
when(it.state) {
WorkInfo.State.ENQUEUED -> if(state.enqueue.time > 10) cancelWork()
}
}
我在任何地方都找不到关于此的任何信息。这可能吗?
感谢您的帮助。
我已经设法创建了一个有点健壮的“Workmanager watcher”。我的意图如下:当 Workmanager 未在 7 秒内完成时,告诉用户发生了错误。 Workmanager 本身永远不会被取消,而且我的功能甚至不与 Workmanager 本身交互。这适用于 99% 的所有情况:
工人帮手
object WorkerHelper {
private var timeStamp by Delegates.notNull<Long>()
private var running = false
private var manuallyStopped = false
private var finished = false
open val maxTime: Long = 7000000000L
// Push the current timestamp, set running to true
override fun start() {
timeStamp = System.nanoTime()
running = true
manuallyStopped = false
finished = false
Timber.d("Mediator started")
}
// Manually stop the WorkerHelper (e.g when Status is Status.Success)
override fun stop() {
if (!running) return else {
running = false
manuallyStopped = true
finished = true
Timber.d("Mediator stopped")
}
}
override fun observeMaxTimeReachedAndCancel(): Flow<Boolean> = flow {
try {
coroutineScope {
// Check if maxTime is not passed with => (System.nanoTime() - timeStamp) <= maxTime
while (running && !finished && !manuallyStopped && (System.nanoTime() - timeStamp) <= maxTime) {
emit(false)
}
// This will be executed only when the Worker is running longer than maxTime
if (!manuallyStopped || !finished) {
emit(true)
running = false
finished = true
this@coroutineScope.cancel()
} else if (finished) {
this@coroutineScope.cancel()
}
}
} catch (e: CancellationException) {
}
}.flowOn(Dispatchers.IO)
然后在我的 Workmanager.enqueueWork 函数中:
fun startDownloadDocumentWork() {
WorkManager.getInstance(context)
.enqueueUniqueWork("Download Document List", ExistingWorkPolicy.REPLACE, downloadDocumentListWork)
pushNotification()
}
private fun pushNotification() {
WorkerHelper.start()
}
最后在我的 ViewModel 中
private fun observeDocumentList() = viewModelScope.launch {
observerWorkerState(documentListWorkInfo).collect {
when(it) {
is Status.Loading -> {
_documentDataState.postValue(Status.loading())
// Launch another Coroutine, otherwise current viewmodelscrope will be blocked
CoroutineScope(Dispatchers.IO).launch {
WorkerHelper.observeMaxTimeReached().collect { lostConnection ->
if (lostConnection) {
_documentDataState.postValue(Status.failed("Internet verbindung nicht da"))
}
}
}
}
is Status.Success -> {
WorkerHelper.finishWorkManually()
_documentDataState.postValue(Status.success(getDocumentList()))
}
is Status.Failure -> {
WorkerHelper.finishWorkManually()
_documentDataState.postValue(Status.failed(it.message.toString()))
}
}
}
}
我还创建了一个函数,可以将 workmanager
的状态转换为自定义状态 class:
状态
sealed class Status<out T> {
data class Success<out T>(val data: T) : Status<T>()
class Loading<T> : Status<T>()
data class Failure<out T>(val message: String?) : Status<T>()
companion object {
fun <T> success(data: T) = Success<T>(data)
fun <T> loading() = Loading<T>()
fun <T> failed(message: String?) = Failure<T>(message)
}
}
函数
suspend inline fun observerWorkerState(workInfoFlow: Flow<WorkInfo>): Flow<Status<Unit>> = flow {
workInfoFlow.collect {
when (it.state) {
WorkInfo.State.ENQUEUED -> emit(Status.loading<Unit>())
WorkInfo.State.RUNNING -> emit(Status.loading<Unit>())
WorkInfo.State.SUCCEEDED -> emit(Status.success(Unit))
WorkInfo.State.BLOCKED -> emit(Status.failed<Unit>("Workmanager blocked"))
WorkInfo.State.FAILED -> emit(Status.failed<Unit>("Workmanager failed"))
WorkInfo.State.CANCELLED -> emit(Status.failed<Unit>("Workmanager cancelled"))
}
}
}
我想检测特定作品已经处于 enqueue
模式多长时间。我需要这些信息,以便通知用户他的状态(例如,当 workmanager 在 enqueue mode
中超过 10 秒时 -> 取消工作 -> 通知用户他需要做 X 以实现 Y)。像这样:
伪代码
workInfo.observe(viewLifecylceOwner) {
when(it.state) {
WorkInfo.State.ENQUEUED -> if(state.enqueue.time > 10) cancelWork()
}
}
我在任何地方都找不到关于此的任何信息。这可能吗?
感谢您的帮助。
我已经设法创建了一个有点健壮的“Workmanager watcher”。我的意图如下:当 Workmanager 未在 7 秒内完成时,告诉用户发生了错误。 Workmanager 本身永远不会被取消,而且我的功能甚至不与 Workmanager 本身交互。这适用于 99% 的所有情况:
工人帮手
object WorkerHelper {
private var timeStamp by Delegates.notNull<Long>()
private var running = false
private var manuallyStopped = false
private var finished = false
open val maxTime: Long = 7000000000L
// Push the current timestamp, set running to true
override fun start() {
timeStamp = System.nanoTime()
running = true
manuallyStopped = false
finished = false
Timber.d("Mediator started")
}
// Manually stop the WorkerHelper (e.g when Status is Status.Success)
override fun stop() {
if (!running) return else {
running = false
manuallyStopped = true
finished = true
Timber.d("Mediator stopped")
}
}
override fun observeMaxTimeReachedAndCancel(): Flow<Boolean> = flow {
try {
coroutineScope {
// Check if maxTime is not passed with => (System.nanoTime() - timeStamp) <= maxTime
while (running && !finished && !manuallyStopped && (System.nanoTime() - timeStamp) <= maxTime) {
emit(false)
}
// This will be executed only when the Worker is running longer than maxTime
if (!manuallyStopped || !finished) {
emit(true)
running = false
finished = true
this@coroutineScope.cancel()
} else if (finished) {
this@coroutineScope.cancel()
}
}
} catch (e: CancellationException) {
}
}.flowOn(Dispatchers.IO)
然后在我的 Workmanager.enqueueWork 函数中:
fun startDownloadDocumentWork() {
WorkManager.getInstance(context)
.enqueueUniqueWork("Download Document List", ExistingWorkPolicy.REPLACE, downloadDocumentListWork)
pushNotification()
}
private fun pushNotification() {
WorkerHelper.start()
}
最后在我的 ViewModel 中
private fun observeDocumentList() = viewModelScope.launch {
observerWorkerState(documentListWorkInfo).collect {
when(it) {
is Status.Loading -> {
_documentDataState.postValue(Status.loading())
// Launch another Coroutine, otherwise current viewmodelscrope will be blocked
CoroutineScope(Dispatchers.IO).launch {
WorkerHelper.observeMaxTimeReached().collect { lostConnection ->
if (lostConnection) {
_documentDataState.postValue(Status.failed("Internet verbindung nicht da"))
}
}
}
}
is Status.Success -> {
WorkerHelper.finishWorkManually()
_documentDataState.postValue(Status.success(getDocumentList()))
}
is Status.Failure -> {
WorkerHelper.finishWorkManually()
_documentDataState.postValue(Status.failed(it.message.toString()))
}
}
}
}
我还创建了一个函数,可以将 workmanager
的状态转换为自定义状态 class:
状态
sealed class Status<out T> {
data class Success<out T>(val data: T) : Status<T>()
class Loading<T> : Status<T>()
data class Failure<out T>(val message: String?) : Status<T>()
companion object {
fun <T> success(data: T) = Success<T>(data)
fun <T> loading() = Loading<T>()
fun <T> failed(message: String?) = Failure<T>(message)
}
}
函数
suspend inline fun observerWorkerState(workInfoFlow: Flow<WorkInfo>): Flow<Status<Unit>> = flow {
workInfoFlow.collect {
when (it.state) {
WorkInfo.State.ENQUEUED -> emit(Status.loading<Unit>())
WorkInfo.State.RUNNING -> emit(Status.loading<Unit>())
WorkInfo.State.SUCCEEDED -> emit(Status.success(Unit))
WorkInfo.State.BLOCKED -> emit(Status.failed<Unit>("Workmanager blocked"))
WorkInfo.State.FAILED -> emit(Status.failed<Unit>("Workmanager failed"))
WorkInfo.State.CANCELLED -> emit(Status.failed<Unit>("Workmanager cancelled"))
}
}
}