Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxJava on Android

RxJava on Android

Describing just how RxJava simplifies your code and your concurrency handling in Android applications.

Jernej Virag

May 15, 2015
Tweet

More Decks by Jernej Virag

Other Decks in Technology

Transcript

  1. Observable<> @GET("/api/search/shares/")
 Observable<RestSearchResults> search(@Query("f") String from,
 @Query("t") String to); @GET("/api/search/shares/")


    void search(@Query("f") String from,
 @Query("t") String to, 
 Callback<RestSearchResults> callback); @GET("/api/search/shares/")
 RestSearchResults search(@Query("f") String from,
 @Query("t") String to); Synchronous interface Callback interface Reactive interface Sync Async TBD
  2. Observable<> @GET("/api/search/shares/")
 Observable<RestSearchResults> search(@Query("f") String from,
 @Query("t") String to); @GET("/api/search/shares/")


    void search(@Query("f") String from,
 @Query("t") String to, 
 Callback<RestSearchResults> callback); @GET("/api/search/shares/")
 RestSearchResults search(@Query("f") String from,
 @Query("t") String to); Synchronous interface Callback interface Reactive interface Sync Async TBD
  3. Observable<> @GET("/api/search/shares/")
 Observable<RestSearchResults> search(@Query("f") String from,
 @Query("t") String to); @GET("/api/search/shares/")


    void search(@Query("f") String from,
 @Query("t") String to, 
 Callback<RestSearchResults> callback); @GET("/api/search/shares/")
 RestSearchResults search(@Query("f") String from,
 @Query("t") String to); Synchronous interface Callback interface Reactive interface Sync Async TBD (!)
  4. Observable<> ApiClient.getAdapter().search(fromCity, toCity, dateString)
 .flatMap(restSearchResults -> Observable.from(restSearchResults.results))
 .filter(restRide -> restRide.date.before(Calendar.getInstance()))


    .map(restRide -> {
 // Localize
 restRide.setLocalizedFrom(context);
 restRide.setLocalizedTo(context);
 return restRide;
 })
 .toSortedList()
  5. A few operators • map() - Object in stream to

    another single object • flatMap() - Object in stream to one or more objects • buffer(), debounce() - Congestion control • filter() - drop objects in stream according to predicate • take(), skip(), single(), first() - get only certain number of objects • https://github.com/ReactiveX/RxJava/wiki/Alphabetical-List-of-Observable-Operators
  6. Making observables • Observable.just( obj ) - single object to

    observable • Observable.defer( function ) - delay execution of fun. • Observable.from( collection ) - turn collection into observable stream • Observable.create( custom source ) - create a stream by calling onNext() / onError() / onComplete Jernej Virag @jernejv
  7. Observable<> ApiClient.getAdapter().search(fromCity, toCity, dateString)
 .flatMap(restSearchResults -> Observable.from(restSearchResults.results))
 .filter(restRide -> restRide.date.before(Calendar.getInstance()))


    .map(restRide -> {
 // Localize
 restRide.setLocalizedFrom(context);
 restRide.setLocalizedTo(context);
 return restRide;
 })
 .toSortedList()
  8. Subscriber ApiClient.getAdapter().search(fromCity, toCity, dateString) …
 .toSortedList() .subscribe(new Subscriber<List<RestRide>>() {
 @Override


    public void onCompleted() { // Nothing to be done }
 @Override
 public void onError(Throwable e) {
 ViewUtils.showErrorMessage(context, "Could not find results…”);
 }
 @Override
 public void onNext(List<RestRide> restRides) {
 resultList.setAdapter(new SearchResultsAdapter(restRides));
 }
 });
  9. Subscriber ApiClient.getAdapter().search(fromCity, toCity, dateString) …
 .toSortedList() .subscribe(new Subscriber<List<RestRide>>() {
 @Override


    public void onCompleted() { // Nothing to be done }
 @Override
 public void onError(Throwable e) {
 ViewUtils.showErrorMessage(context, "Could not find results…”);
 }
 @Override
 public void onNext(List<RestRide> restRides) {
 resultList.setAdapter(new SearchResultsAdapter(restRides));
 }
 });
  10. Subscriber ApiClient.getAdapter().search(fromCity, toCity, dateString) …
 .toSortedList() .subscribe(new Subscriber<List<RestRide>>() {
 @Override


    public void onCompleted() { // Nothing to be done }
 @Override
 public void onError(Throwable e) {
 ViewUtils.showErrorMessage(context, "Could not find results…”);
 }
 @Override
 public void onNext(List<RestRide> restRides) {
 resultList.setAdapter(new SearchResultsAdapter(restRides));
 }
 });
  11. Subscriber ApiClient.getAdapter().search(fromCity, toCity, dateString) …
 .toSortedList() .subscribe(new Subscriber<List<RestRide>>() {
 @Override


    public void onCompleted() { // Nothing to be done }
 @Override
 public void onError(Throwable e) {
 ViewUtils.showErrorMessage(context, "Could not find results…”);
 }
 @Override
 public void onNext(List<RestRide> restRides) {
 resultList.setAdapter(new SearchResultsAdapter(restRides));
 }
 });
  12. More examples RxLocationProvider.getCurrentLocation()
 .map(location -> Geocoder.getAddressForLocation())
 .map(address -> ApiClient.getBitmapForCity(address))
 .onErrorReturn(throwable

    -> placeholderBitmap)
 .defaultIfEmpty(placeholderBitmap)
 
 .subscribeOn(Schedulers.io())
 .observeOn(AndroidSchedulers.mainThread())
 
 .subscribe(bitmap -> {
 headerImageView.setImageDrawable( new FadeInDrawable(bitmap));
 });
  13. More examples Observable<List<SearchResult>> groupedResults = TextProvider.findStringInDocument(getContext(), document, searchString, configuration.getSnippetLength())
 .map(searchResult

    -> {
 searchResult.setHighlightColor(configuration.getHighlightColor());
 return searchResult;
 }
 })
 .buffer(300, TimeUnit.MILLISECONDS)
 .onBackpressureBuffer() … groupedResults.debounce() .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Subscriber<List<SearchResult>>() {
 @Override
 public void onCompleted() {
 String searchCompleted = getResources().getString(R.string.pspdf__search_complete);
 String matchesFound = getResources().getQuantityString(R.plurals.pspdf__search_results_found, adapter.getCount(), adapter.getCount());
 SpannableString str = new SpannableString(searchCompleted + "\n" + matchesFound);
 footer.setText(str);
 footer.setVisibility(View.VISIBLE);
 throbber.setVisibility(View.INVISIBLE);
 }
 
 @Override
 public void onError(Throwable throwable) { footer.setText(“Results could not be retrieved.”); 
 }
 
 @Override
 public void onNext(List<SearchResult> searchResults) {
 adapter.addResults(searchResults);
 EventBus.getDefault().post(new Events.NewSearchResults(searchResults));
 }
 });
  14. The downsides • On Java 6 it requires creation of

    A LOT of anonymous classes • It’s generally not easy on GC • It’s very easy to leak references in the anon. classes • Use RxAndroid bind() calls to help you • It’s a rather large dependency Jernej Virag @jernejv
  15. Where to start • RxJava GitHub + Wiki Documentation
 https://github.com/ReactiveX/RxJava

    • Grokking RxJava / Android, Parts 1-4
 http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/ • Fragmented Podcast Episode 3/4
 https://player.fm/series/fragmented-67211/episode-3-rxjava-with-dan-lew-part-1 
 https://player.fm/series/fragmented-67211/episode-4-rxjava-with-dan-lew-part-2 Jernej Virag @jernejv
  16. Neat stuff • Retrofit
 https://square.github.io/retrofit/ • SqlBrite
 https://github.com/square/sqlbrite • Reactive

    Location
 https://github.com/mcharmas/Android-ReactiveLocation Jernej Virag @jernejv