新しいアーキテクチャコンポーネントWorkManagerを初めて使用します。RetrofitとRxJavaを介してAPI呼び出しを行います。
ここでの私の使用例は、バックエンドから新しい投稿を取得し、通知を表示して、ウィジェットを更新することです。
したがって、Workerクラスの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;
}
DoWork()メソッドには戻り値があるため、Workerクラス内でRxJavaコードを使用する正しい方法は私の質問です。したがって、Rxコードを同期化する必要があります。
ノンブロッキングRxアプローチを使用している場合、値を返す方法(成功-失敗-再試行)
WorkManagerバージョン1.0.0-alpha12
以降、彼らはwork-rxjava2
と呼ばれる新しい成果物を追加しました。この成果物には、この目的のために RxWorker
クラスが含まれます。 ListenableWorker
がSingle<Result>
を必要とする特殊なケースです。
実装するには、最初にbuild.gradle
に正しいアーティファクトを含めるようにしてください。
dependencies {
...
implementation "Android.Arch.work:work-runtime-ktx:1.0.0-beta01"
implementation "Android.Arch.work:work-rxjava2:1.0.0-beta01"
}
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() }
}
}
編集: WorkManagerはRxWorker
を正式にサポートするようになりました。詳細については、上記の回答をご覧ください。
doWork
はバックグラウンドスレッドで発生します。したがって、ブロックしても安全です。 Observable
を返す前に、Result
が完了するのを待つ必要があります。
また、非同期APIを使用してこれを簡単にすることにも取り組んでいます。乞うご期待。
はい、Rxコードを同期化します。 doWork のドキュメントは最小限ですが、説明
実際のバックグラウンド処理を行うには、このメソッドをオーバーライドします。
ブロックされることが予想されるか、少なくとも許可されることを意味します。そしてもちろん、ネットワーク要求が解決されるまで、doWork
が何を返すべきかを知ることはできません。
私は解決策を見つけました。非同期ジョブには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
}
}