2016-04-23 13 views
5

AndroidアプリケーションでrxAndroidとrxKotlinを使用してネットワーク要求を非同期に処理しています。今すぐスナックバーボタンをクリックした後で失敗したネットワークリクエストを再試行したいと思います。RxAndroid - クリック時に観測再試行

私のコード今:

val citiesService = ApiFactory.citiesService 

citiesService.cities() 
    .subscribeOn(Schedulers.newThread()) // fetch List<String> 
    .flatMap { Observable.from(it) }  // convert to sequence of String 
    .flatMap { city -> 
     citiesService.coordinates(city) // fetch DoubleArray 
      .map { City(city, it) }  // convert to City(String, DoubleArray) 
     } 
    .toList() 
    .observeOn(AndroidSchedulers.mainThread()) 
    .doOnNext { 
     listView.setOnItemClickListener { adapterView, view, position, id -> 
      onItemClick(it[position]) 
     } 
    } 
    .map { it.map { it.getName(activity) } } 
    .subscribe(
     { listAdapter = setupAdapter(it) }, 
     { showErrorSnackbar() } // handle error 
    ) 

fun showErrorSnackbar() { 
     Snackbar.make(listView, getString(R.string.not_available_msg), Snackbar.LENGTH_INDEFINITE) 
       .setAction(getString(R.string.snack_retry_btn), { 
        // retry observable 
       }) 
       .show() 
    } 

都市改造のためのインタフェース:

interface CitiesService { 

    @GET("api/v1/cities") 
    fun cities(): Observable<List<String>> 

    @GET("api/v1/cities/{city}/coordinates") 
    fun coordinates(@Path("city") city: String): Observable<DoubleArray> 
} 

のAPI工場:

object ApiFactory { 

    val citiesService: CitiesService 
     get() = retrofit.create(CitiesService::class.java) 

    private val retrofit: Retrofit 
     get() = Retrofit 
      .Builder() 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .baseUrl(BASE_URL) 
      .build() 
} 

私は、このような方法で観測可能を再起動することができますどのように?

+0

リクエストをトリガしているのは何ですか?私はあなたのコードからそれを見ることはできません。 'cities()'を呼び出すと新しいリクエストがトリガされますか? –

+0

上記のコードを追加しました。はい、 'cities()'が新しいリクエストを引き起こします – Michael

+0

次に、 'citiesService.cities()...'リアクティブチェーンを新しいメソッドにラップして、Snackbarのアクションリスナーから呼び出すことができます。 –

答えて

1

私はあなたが絶対的なやり方ではなく本当に反応的な方法を提案することができます。

直後購読()メソッドのコードを挿入します。

.retryWhen(retryHandler -> 
      retryHandler.flatMap(nothing -> retrySubject.asObservable())) 
.subscribe() 

更新対象がちょうどです:

@NonNull 
private final PublishSubject<Void> retrySubject = PublishSubject.create(); 

とスナックバー上に、このメソッドを呼び出すクリック:

public void update() { 
    retrySubject.onNext(null); 
} 

すべてretryWhenメソッドは文字通りやり直します。

この手法ではエラーは決してサブスクライバに伝わらないものの、retryHandlerフラットマップにエラーコンディショニングを追加できますが、これは別の話です。

P.S.申し訳ありませんが、これはretrolambdasのJavaコードでしたが、これを簡単にKotlinに変換します。

+0

私はこのアプローチをhttps://android.jlelse.eu/rx-grokking-retrywand-and-repeatwhen-and-android-development-examples-af5c3ed0872bから取ってみました。しかし、Androidスタジオは、「メソッドasObservableを解決できません。 () ' –

+0

asObservable()メソッドがRxJava2から削除されたのと同じエラーが発生しましたが、他の方法でも同じ機能を得ることができます – Neha

関連する問題