Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Implementing Your Own Operators

David Gross edited this pageMay 19, 2015 ·22 revisions

You can implement your own Observable operators. This page shows you how.

If your operator is designed tooriginate an Observable, rather than to transform or react to a source Observable, use thecreate( ) method rather than trying to implementObservable manually. Otherwise, you can create a custom operator by following the instructions on this page.

If your operator is designed to act on the individual items emitted by a source Observable, follow the instructions underSequence Operators below. If your operator is designed to transform the source Observable as a whole (for instance, by applying a particular set of existing RxJava operators to it) follow the instructions underTransformational Operators below.

(Note: in Xtend, a Groovy-like language, you can implement your operators asextension methods and can thereby chain them directly without using the methods described on this page. SeeRxJava and Xtend for details.)

Sequence Operators

The following example shows how you can use thelift( ) operator to chain your custom operator (in this example:myOperator) alongside standard RxJava operators likeofType andmap:

fooObservable= barObservable.ofType(Integer).map({it*2}).lift(new myOperator<T>()).map({"transformed by myOperator:"+ it});

The following section shows how you form the scaffolding of your operator so that it will work correctly withlift( ).

Implementing Your Operator

Define your operator as a public class that implements theOperator interface, like so:

publicclassmyOperator<T>implementsOperator<T> {publicmyOperator(/* any necessary params here */ ) {/* any necessary initialization here */  }@OverridepublicSubscriber<?superT>call(finalSubscriber<?superT>s) {returnnewSubscriber<t>(s) {@OverridepublicvoidonCompleted() {/* add your own onCompleted behavior here, or just pass the completed notification through: */if(!s.isUnsubscribed()) {s.onCompleted();        }      }@OverridepublicvoidonError(Throwablet) {/* add your own onError behavior here, or just pass the error notification through: */if(!s.isUnsubscribed()) {s.onError(t);        }      }@OverridepublicvoidonNext(Titem) {/* this example performs some sort of operation on each incoming item and emits the results */if(!s.isUnsubscribed()) {transformedItem =myOperatorTransformOperation(item);s.onNext(transformedItem);        }      }    };  }}

Transformational Operators

The following example shows how you can use thecompose( ) operator to chain your custom operator (in this example, an operator calledmyTransformer that transforms an Observable that emits Integers into one that emits Strings) alongside standard RxJava operators likeofType andmap:

fooObservable= barObservable.ofType(Integer).map({it*2}).compose(new myTransformer<Integer,String>()).map({"transformed by myOperator:"+ it});

The following section shows how you form the scaffolding of your operator so that it will work correctly withcompose( ).

Implementing Your Transformer

Define your transforming function as a public class that implements theTransformer interface, like so:

publicclassmyTransformer<Integer,String>implementsTransformer<Integer,String> {publicmyTransformer(/* any necessary params here */ ) {/* any necessary initialization here */  }@OverridepublicObservable<String>call(Observable<Integer>source) {/*     * this simple example Transformer applies map() to the source Observable     * in order to transform the "source" observable from one that emits     * integers to one that emits string representations of those integers.     */returnsource.map(newFunc1<Integer,String>() {@OverridepublicStringcall(Integert1) {returnString.valueOf(t1);      }    } );  }}

See also

Other Considerations

  • Your sequence operator may want to checkits Subscriber’sisUnsubscribed( ) status before it emits any item to (or sends any notification to) the Subscriber. There’s no need to waste time generating items that no Subscriber is interested in seeing.
  • Take care that your sequence operator obeys the core tenets of the Observable contract:
    • It may call a Subscriber’sonNext( ) method any number of times, but these calls must be non-overlapping.
    • It may call either a Subscriber’sonCompleted( ) oronError( ) method, but not both, exactly once, and it may not subsequently call a Subscriber’sonNext( ) method.
    • If you are unable to guarantee that your operator conforms to the above two tenets, you can add theserialize( ) operator to it, which will force the correct behavior.
  • Keep an eye onIssue #1962 — there are plans to create a test scaffold that you can use to write tests which verify that your new operator conforms to the Observable contract.
  • Do not block within your operator.
  • When possible, you should compose new operators by combining existing operators, rather than implementing them with new code. RxJava itself does this with some of its standard operators, for example:
  • If your operator uses functions or lambdas that are passed in as parameters (predicates, for instance), note that these may be sources of exceptions, and be prepared to catch these and notify subscribers viaonError( ) calls.
    • Some exceptions are considered “fatal” and for them there’s no point in trying to callonError( ) because that will either be futile or will just compound the problem. You can use theExceptions.throwIfFatal(throwable) method to filter out such fatal exceptions and rethrow them rather than try to notify about them.
  • In general, notify subscribers of error conditions immediately, rather than making an effort to emit more items first.
  • Be aware that “null” is a valid item that may be emitted by an Observable. A frequent source of bugs is to test some variable meant to hold an emitted item againstnull as a substitute for testing whether or not an item was emitted. An emission of “null” is still an emission and is not the same as not emitting anything.
  • It can be tricky to make your operator behave well inbackpressure scenarios. SeeAdvanced RxJava, a blog from Dávid Karnok, for a good discussion of the factors at play and how to deal with them.

Copyright (c) 2016-present, RxJava Contributors.
Twitter @RxJava |Gitter @RxJava

Clone this wiki locally


[8]ページ先頭

©2009-2025 Movatter.jp