web-dev-qa-db-ja.com

ワーカー内の同期または非同期Rxjava(WorkManagerコンポーネントから)正しい選択は何ですか?

新しいアーキテクチャコンポーネント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アプローチを使用している場合、値を返す方法(成功-失敗-再試行)

18
Mohamed Ibrahim

WorkManagerバージョン1.0.0-alpha12以降、彼らはwork-rxjava2と呼ばれる新しい成果物を追加しました。この成果物には、この目的のために RxWorker クラスが含まれます。 ListenableWorkerSingle<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() }
    }
}
26
Semanticer

編集: WorkManagerはRxWorkerを正式にサポートするようになりました。詳細については、上記の回答をご覧ください。

doWorkはバックグラウンドスレッドで発生します。したがって、ブロックしても安全です。 Observableを返す前に、Resultが完了するのを待つ必要があります。

また、非同期APIを使用してこれを簡単にすることにも取り組んでいます。乞うご期待。

6
Rahul

はい、Rxコードを同期化します。 doWork のドキュメントは最小限ですが、説明

実際のバックグラウンド処理を行うには、このメソッドをオーバーライドします。

ブロックされることが予想されるか、少なくとも許可されることを意味します。そしてもちろん、ネットワーク要求が解決されるまで、doWorkが何を返すべきかを知ることはできません。

1
TKK

私は解決策を見つけました。非同期ジョブには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
   }
}
0
Edgar Khimich