RxJava Advent Calendar 2015の最終日です。軽めにいきます。
Observableでリストを得るインターフェイスを Observable<T>
にすべきか Single<List<T>>
にするべきか迷うことがあると思います。
結論からいえば、迷った時は Single<List<T>>
だろうと思っています。
List<T>
を得るときは、ほとんどの場合 ListAdapter
などにそのまま渡すことになるでしょう。したがって、 Observable<T>
インターフェイスがあっても結局 Observable#toList()
で Observable<List<T>>
に変換することになります。
また、典型的な二つのケース、Web API Clientを使う場合とlocal DBを使う場合を考えます。
Web API Clientの場合
Web API clientを使う場合は、T
をそのまま返すのではなくresponse objectを返すべきです。実際に、Retrofit 2.0ではそのようなことができるインターフェイスになっています。
retrofit/RxJavaCallAdapterFactoryTest.java at master · square/retrofit · GitHub
// RxJavaCallAdapterFactoryTest.java interface Service { @GET("/") Observable<String> observableBody(); # Tそのまま @GET("/") Observable<Response<String>> observableResponse(); # retrofit2のResponse<T> @GET("/") Observable<Result<String>> observableResult(); # adapter-rxjavaのResult<T> (Response<T>のラッパー) @GET("/") Single<String> singleBody(); @GET("/") Single<Response<String>> singleResponse(); @GET("/") Single<Result<String>> singleResult(); }
したがって Single<List<T>>
か Observable<List<T>>
かという議論は必要ありませんが、実際には Single<Result<List<T>>>
だったりもするので実質的には Single<List<T>>
と同じことです。
DBから取得した値の場合
DB(SQLite)からの読みこみは十分に速いので、まとめて読みこんでListAdapter
に渡すのではなく、ひとつのセルを構築するたびにDB
から値を一つ読み込むという方法でも実用上問題ありません。そしてこの場合は、RxJavaインターフェイスを使う必要はありません。
RxJavaのオペレータを使いたい場合は Single<List<T>>
を得られれば flatMapObservable()
で Observable<T>
に変換することもできますから、 Single<List<T>>
だけあれば十分かと思います。
List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); // Single<List<String>> があるとする Single<List<String>> listSingle = Single.just(list); // flatMapObservable() で Observable<String> に変換する listSingle.flatMapObservable(new Func1<List<String>, Observable<String>>() { @Override public Observable<String> call(List<String> strings) { return Observable.from(strings); } }).forEach(new Action1<String>() { @Override public void call(String s) { Log.d("XXX", s); // "foo", "bar" } });
以上です。