Worker 内部的同步或异步 Rxjava(来自 WorkManager 组件)什么是正确的选择?
Synchronous or Asynchronous Rxjava inside the Worker (from WorkManager component) what's the right choice?
我是新架构组件 WorkManager 的新手,我通过 Retrofit 和 RxJava 进行 API 调用。
我在这里的用例是从后端获取新帖子,然后显示通知,并更新小部件。
所以来自 Worker class 的 doWork() 方法中的代码可能看起来像这样。
@NonNull
@Override
public Result doWork() {
AppDependencies appDependencies = new AppDependencies((Application) getApplicationContext());
Repository repository = appDependencies.getRepository();
repository.getNewPosts()
.flatMap(newPosts -> repository.inserPosts(newPosts).toObservable())
.doOnError(Timber::e)
//if success - > return Result.SUCCESS,
// -> show notification
// -> update widget
// error-> return Result.Failure
.dontKnowWhatBestNextThing; //blocking or subscribing
//if we reached here then Retry
return Result.RETRY;
}
我的问题是在 Worker Class 中使用 RxJava 代码的正确方法是什么,因为 doWork() 方法有一个 return 值,所以我是否必须使 Rx 代码同步.
如果我使用非阻塞 Rx 方法,我如何 return 值(成功 - 失败 - 重试)
是的,使 Rx 代码同步。 doWork 的文档很少,但描述
Override this method to do your actual background processing.
暗示它被预期或至少被允许阻止。当然,在网络请求得到解决之前,您无法知道 doWork
应该 return 什么。
编辑: WorkManager 现在正式支持 RxWorker
。查看上面的答案以获取更多信息。
doWork
发生在后台线程上。所以阻止是安全的。您应该等待 Observable
完成,然后再 return 一个 Result
。
我们还致力于通过异步 API 简化这一过程。敬请期待。
自 WorkManager 版本 1.0.0-alpha12
起,他们添加了一个名为 work-rxjava2
的新工件,其中包含 RxWorker
class 正是出于此目的。这是 ListenableWorker
期望 Single<Result>
的特例。
要实施它,首先确保您在 build.gradle
:
中包含正确的工件
dependencies {
...
implementation "android.arch.work:work-runtime-ktx:$work_version"
implementation "android.arch.work:work-rxjava2:$work_version"
}
并实现你的 RxWorker
:
class MyRxWorker(context : Context, params : WorkerParameters) : RxWorker(context, params) {
val remoteService = RemoteService()
override fun createWork(): Single<Result> {
return remoteService.getMySingleResponse()
.doOnSuccess { /* process result somehow */ }
.map { Result.success() }
.onErrorReturn { Result.failure() }
}
}
我找到了解决方案。
您应该使用 RxWorker 或 SettableFuture 进行异步作业
这是我获取当前位置的解决方案。像魅力一样工作
class LocationWorker(context: Context, private val workerParams: WorkerParameters) :
ListenableWorker(context, workerParams) {
lateinit var mFuture: SettableFuture<ListenableWorker.Result>
private var fusedLocationProviderClient = FusedLocationProviderClient(context)
@SuppressLint("RestrictedApi", "MissingPermission")
override fun startWork(): ListenableFuture<Result> {
val uniqueId = workerParams.inputData.getString(UNIQUE_ID_KEY)
mFuture = SettableFuture.create()
Timber.d("mFutureStart")
fusedLocationProviderClient.lastLocation.addOnSuccessListener { location ->
Timber.d("location == $location")
if (location != null) {
mFuture.set(Result.success())
} else mFuture.set(Result.failure())
}
return mFuture
}
}
您可以将 Rxjava 和协程与工作管理器一起使用。看看这个 Medium post。希望它能帮助你。谢谢。
我是新架构组件 WorkManager 的新手,我通过 Retrofit 和 RxJava 进行 API 调用。
我在这里的用例是从后端获取新帖子,然后显示通知,并更新小部件。
所以来自 Worker class 的 doWork() 方法中的代码可能看起来像这样。
@NonNull
@Override
public Result doWork() {
AppDependencies appDependencies = new AppDependencies((Application) getApplicationContext());
Repository repository = appDependencies.getRepository();
repository.getNewPosts()
.flatMap(newPosts -> repository.inserPosts(newPosts).toObservable())
.doOnError(Timber::e)
//if success - > return Result.SUCCESS,
// -> show notification
// -> update widget
// error-> return Result.Failure
.dontKnowWhatBestNextThing; //blocking or subscribing
//if we reached here then Retry
return Result.RETRY;
}
我的问题是在 Worker Class 中使用 RxJava 代码的正确方法是什么,因为 doWork() 方法有一个 return 值,所以我是否必须使 Rx 代码同步.
如果我使用非阻塞 Rx 方法,我如何 return 值(成功 - 失败 - 重试)
是的,使 Rx 代码同步。 doWork 的文档很少,但描述
Override this method to do your actual background processing.
暗示它被预期或至少被允许阻止。当然,在网络请求得到解决之前,您无法知道 doWork
应该 return 什么。
编辑: WorkManager 现在正式支持 RxWorker
。查看上面的答案以获取更多信息。
doWork
发生在后台线程上。所以阻止是安全的。您应该等待 Observable
完成,然后再 return 一个 Result
。
我们还致力于通过异步 API 简化这一过程。敬请期待。
自 WorkManager 版本 1.0.0-alpha12
起,他们添加了一个名为 work-rxjava2
的新工件,其中包含 RxWorker
class 正是出于此目的。这是 ListenableWorker
期望 Single<Result>
的特例。
要实施它,首先确保您在 build.gradle
:
dependencies {
...
implementation "android.arch.work:work-runtime-ktx:$work_version"
implementation "android.arch.work:work-rxjava2:$work_version"
}
并实现你的 RxWorker
:
class MyRxWorker(context : Context, params : WorkerParameters) : RxWorker(context, params) {
val remoteService = RemoteService()
override fun createWork(): Single<Result> {
return remoteService.getMySingleResponse()
.doOnSuccess { /* process result somehow */ }
.map { Result.success() }
.onErrorReturn { Result.failure() }
}
}
我找到了解决方案。 您应该使用 RxWorker 或 SettableFuture 进行异步作业
这是我获取当前位置的解决方案。像魅力一样工作
class LocationWorker(context: Context, private val workerParams: WorkerParameters) :
ListenableWorker(context, workerParams) {
lateinit var mFuture: SettableFuture<ListenableWorker.Result>
private var fusedLocationProviderClient = FusedLocationProviderClient(context)
@SuppressLint("RestrictedApi", "MissingPermission")
override fun startWork(): ListenableFuture<Result> {
val uniqueId = workerParams.inputData.getString(UNIQUE_ID_KEY)
mFuture = SettableFuture.create()
Timber.d("mFutureStart")
fusedLocationProviderClient.lastLocation.addOnSuccessListener { location ->
Timber.d("location == $location")
if (location != null) {
mFuture.set(Result.success())
} else mFuture.set(Result.failure())
}
return mFuture
}
}
您可以将 Rxjava 和协程与工作管理器一起使用。看看这个 Medium post。希望它能帮助你。谢谢。