【问题标题】:How to dispose Rx in WorkManager?如何在 WorkManager 中处理 Rx?
【发布时间】:2018-10-15 23:26:49
【问题描述】:

我实现了AlarmManager,以便在用户向任务添加截止日期时发送通知。但是,当用户关闭设备时,所有警报都会丢失。现在我正在更新BroadcastReceiver 以接收android.intent.action.BOOT_COMPLETED 并重新安排为每个任务设置的所有警报。

我的第一次尝试是在BroadcastReceiver 中获取所有到期日期高于当前时间的任务的Rx Single,然后重新安排所有警报。问题是一旦BroadcastReceiver 没有生命周期,我就无法处置Observable。另外,it seems that this is not a good approach

在我的研究中,IntentService 是这个案例的一个很好的解决方案,但我正在进入新的 WorkManager 库,OneTimeWorkRequest 看起来是一个很好且简单的解决方案。

Worker 正在被调用并正确执行,但我无法释放 Observable,因为从未调用过 onStopped 方法。

这是基于this snippet的实现:

class TaskAlarmWorker(context: Context, params: WorkerParameters) :
    Worker(context, params), KoinComponent {

    private val daoRepository: DaoRepository by inject()

    private val compositeDisposable = CompositeDisposable()

    override fun doWork(): Result {
        Timber.d("doWork")

        val result = LinkedBlockingQueue<Result>()

        val disposable =
            daoRepository.getTaskDao().getAllTasks().applySchedulers().subscribe(
            { result.put(Result.SUCCESS) },
            { result.put(Result.FAILURE) }
        )

        compositeDisposable.add(disposable)

        return try {
            result.take()
        } catch (e: InterruptedException) {
            Result.RETRY
        }
    }

    override fun onStopped(cancelled: Boolean) {
        Timber.d("onStopped")
        compositeDisposable.clear()
    }
}
  • WorkManager 是否适合这种情况?
  • 是否可以正确处理Observable

【问题讨论】:

    标签: android alarmmanager rx-android intentservice android-workmanager


    【解决方案1】:
    • 是的WorkManager 是一个很好的解决方案(甚至可能是最好的解决方案)
    • 您应该使用RxWorker 而不是Worker。这是一个例子:

      1. 实现它。将androidx.work:work-rxjava2:$work_version 添加到您的build.gradle 文件作为依赖项。

      2. RxWorker 类扩展您的类,然后覆盖createWork() 函数。

    class TaskAlarmWorker(context: Context, params: WorkerParameters) :
        RxWorker(context, params), KoinComponent {
    
        private val daoRepository: DaoRepository by inject()  
    
        override fun createWork(): Single<Result> {
            Timber.d("doRxWork")
    
         return daoRepository.getTaskDao().getAllTasks()
                    .doOnSuccess { /* process result somehow */ }
                    .map { Result.success() }
                    .onErrorReturn { Result.failure() }          
    
        }
    
    }
    

    关于 RxWorker 的重要说明

    • createWork() 方法在主线程上调用,但返回的 single 在后台线程上订阅。
    • 您无需担心销毁 Observer,因为 RxWorker 会在工作停止时自动销毁它。
    • 返回值为 Result.failure() 的 Single 和返回错误的 Single 都会导致 worker 进入失败状态。
    • 您可以覆盖onStopped 函数以执行更多操作。

    阅读更多:

    【讨论】:

    • 但这仅适用于发出一个值的单个。如果你想使用一个一直发射直到工作完成的 Observable 怎么办? (如下载进度条)
    • @MyHouse @MyHouse 这个Single&lt;Result&gt; 用于告诉WorkManeger 我的工作已经完成,因此请处置资源。对于下载情况,您可以使用 Flowable(或 Observable)然后将结果映射到 onComplete 或 onError 事件中,此外,您不应在 onNext 事件中返回任何内容。
    【解决方案2】:

    你可以用onStoped()方法清除它然后compositeDisposable.dispose();

    然后拨打super.onStoped()

    【讨论】:

    • Worker 类中没有 onStop() 方法,我已经实现的方法 onStopped() 永远不会被调用。
    • 它在工作完成时调用,Android 操作系统知道工作何时完成,但另一种解决方案是您可以在另一个班级中拨打电话并在需要时处理您的工作
    • 您可以创建另一个类以使您的实现不在 Worker Class 中使用 CompositeDisposable :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2019-05-24
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多