RxJavaでのカスタムオペレーターの実装
1. 概要
このクイックチュートリアルでは、RxJavaを使用してカスタム演算子を作成する方法を示します。
この単純な演算子とトランスフォーマーを、クラスまたは単純な関数として構築する方法について説明します。
2. Mavenの構成
まず、pom.xmlにrxjavaの依存関係があることを確認する必要があります。
io.reactivex
rxjava
1.3.0
Maven Centralでrxjavaの最新バージョンを確認できます。
3. カスタムオペレーター
We can create our custom operator by implementing Operator interface、次の例では、Stringから英数字以外の文字を削除するための単純な演算子を実装しました。
public class ToCleanString implements Operator {
public static ToCleanString toCleanString() {
return new ToCleanString();
}
private ToCleanString() {
super();
}
@Override
public Subscriber super String> call(final Subscriber super String> subscriber) {
return new Subscriber(subscriber) {
@Override
public void onCompleted() {
if (!subscriber.isUnsubscribed()) {
subscriber.onCompleted();
}
}
@Override
public void onError(Throwable t) {
if (!subscriber.isUnsubscribed()) {
subscriber.onError(t);
}
}
@Override
public void onNext(String item) {
if (!subscriber.isUnsubscribed()) {
final String result = item.replaceAll("[^A-Za-z0-9]", "");
subscriber.onNext(result);
}
}
};
}
}
上記の例では、操作を適用してアイテムが不要になるので、サブスクライバーがサブスクライブされているかどうかを確認する必要があります。
メソッドをチェーンし、静的インポートを使用する場合はWe are also restricting instance creation only to static factory methods to achieve a more user-friendly readability。
そして今、lift演算子を使用して、カスタム演算子を他の演算子と簡単にチェーンできます。
observable.lift(toCleanString())....
カスタムオペレーターの簡単なテストを次に示します。
@Test
public void whenUseCleanStringOperator_thenSuccess() {
List list = Arrays.asList("john_1", "tom-3");
List results = new ArrayList<>();
Observable observable = Observable
.from(list)
.lift(toCleanString());
observable.subscribe(results::add);
assertThat(results, notNullValue());
assertThat(results, hasSize(2));
assertThat(results, hasItems("john1", "tom3"));
}
4. 変成器
Transformerインターフェースを実装することでオペレーターを作成することもできます。
public class ToLength implements Transformer {
public static ToLength toLength() {
return new ToLength();
}
private ToLength() {
super();
}
@Override
public Observable call(Observable source) {
return source.map(String::length);
}
}
トランスフォーマーtoLengthを使用して、オブザーバブルをStringからInteger単位の長さに変換することに注意してください。
トランスフォーマーを使用するには、compose演算子が必要です。
observable.compose(toLength())...
以下に簡単なテストを示します。
@Test
public void whenUseToLengthOperator_thenSuccess() {
List list = Arrays.asList("john", "tom");
List results = new ArrayList<>();
Observable observable = Observable
.from(list)
.compose(toLength());
observable.subscribe(results::add);
assertThat(results, notNullValue());
assertThat(results, hasSize(2));
assertThat(results, hasItems(4, 3));
}
lift(Operator)はオブザーバブルのサブスクライバーで動作しますが、compose(Transformer)はオブザーバブル自体で動作します。
カスタム演算子を作成するとき、オブザーバブル全体を操作する場合はTransformerを選択し、オブザーバブルによって放出されるアイテムを操作する場合はOperatorを選択する必要があります。
5. 関数としてのカスタム演算子
カスタム演算子をpublic classの代わりに関数として実装できます:
Operator cleanStringFn = subscriber -> {
return new Subscriber(subscriber) {
@Override
public void onCompleted() {
if (!subscriber.isUnsubscribed()) {
subscriber.onCompleted();
}
}
@Override
public void onError(Throwable t) {
if (!subscriber.isUnsubscribed()) {
subscriber.onError(t);
}
}
@Override
public void onNext(String str) {
if (!subscriber.isUnsubscribed()) {
String result = str.replaceAll("[^A-Za-z0-9]", "");
subscriber.onNext(result);
}
}
};
};
そして、ここに簡単なテストがあります:
List results = new ArrayList<>();
Observable.from(Arrays.asList("[email protected]", "or-an?ge"))
.lift(cleanStringFn)
.subscribe(results::add);
assertThat(results, notNullValue());
assertThat(results, hasSize(2));
assertThat(results, hasItems("apple", "orange"));
同様に、Transformerの例の場合:
@Test
public void whenUseFunctionTransformer_thenSuccess() {
Transformer toLengthFn = s -> s.map(String::length);
List results = new ArrayList<>();
Observable.from(Arrays.asList("apple", "orange"))
.compose(toLengthFn)
.subscribe(results::add);
assertThat(results, notNullValue());
assertThat(results, hasSize(2));
assertThat(results, hasItems(5, 6));
}
6. 結論
この記事では、RxJavaオペレーターの作成方法を示しました。
そして、いつものように、完全なソースコードはover on GitHubで見つけることができます。