Je suis nouveau dans le nouveau composant d'architecture WorkManager, je fais mes appels d'API via Retrofit et RxJava.
Mon cas d’utilisation ici est d’obtenir de nouvelles publications du Backend, puis d’afficher une notification et de mettre à jour un widget.
Ainsi, le code de la méthode doWork () de la classe Worker peut ressembler à quelque chose comme ceci.
@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;
}
Ma question est de savoir quelle est la bonne façon d'utiliser un code RxJava dans la classe Worker car la méthode doWork () a une valeur de retour, dois-je donc rendre le code Rx synchrone.
si j'utilise l'approche Rx non bloquante, comment puis-je retourner de la valeur (Succès - Échec - Réessayer)
Depuis la version 1.0.0-alpha12
de WorkManager, ils ont ajouté un nouvel artefact appelé work-rxjava2
qui inclut RxWorker
class exactement à cette fin. C'est un cas particulier de ListenableWorker
en attente de Single<Result>
.
Pour l'implémenter, assurez-vous d'abord d'inclure les artefacts corrects dans votre build.gradle
:
dependencies {
...
implementation "Android.Arch.work:work-runtime-ktx:1.0.0-beta01"
implementation "Android.Arch.work:work-rxjava2:1.0.0-beta01"
}
Et implémentez votre 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() }
}
}
Edition: WorkManager prend désormais officiellement en charge une RxWorker
. Jetez un oeil à la réponse ci-dessus pour plus d'informations.
doWork
se produit sur un thread d'arrière-plan. Donc, il est sécuritaire de bloquer. Vous devez attendre la fin de la Observable
avant de renvoyer une Result
.
Nous travaillons également à rendre cela plus facile avec les API asynchrones. Restez à l'écoute.
J'ai trouvé la solution. Vous devez utiliser RxWorker ou SettableFuture pour un travail asynchrone
Ceci est ma solution pour obtenir l'emplacement actuel. Travailler comme un charme
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
}
}
Oui, rendre le code Rx synchrone. La documentation de doWork est minimale, mais l’utilisation du mot «arrière-plan» implique qu’il est attendu ou au moins autorisé à bloquer. Et bien sûr, vous ne pouvez pas savoir ce que doWork
doit renvoyer avant que la requête réseau ait été résolue.