The import

I’m sure you’re all familiar with Both ReactiveX and RxJava, as ReactiveX and RxJava are now ubiquitous in blogs on every technology-related site.

ReactiveX

  • ReactiveX stands for Reactive Extensions.
  • “A library for composing Asynchronous and Event-based programs using Observable sequences for the Java VM” To form asynchronous, event-based libraries using observable sequences.
  • Rx is a programming model that aims to provide a consistent programming interface to help developers handle asynchronous data flows more easily. It was developed by a team led by Microsoft architect Erik Meijer and opened source in November 2012. It is implemented in every common programming language. Java,C#,PHP,Swift, Scala, etc. The community site is reactivex.io.
  • More than just a programming interface, ReactiveX was a breakthrough in programming thought that influenced many other libraries and frameworks as well as programming languages.

About responsive programming

  • Event buses, or the common click Event, are an asynchronous stream of events that you can observe and do custom operations based on. Reactive is based on this idea. You can create data streams for everything, not just click and hover events. Streams are cheap and ubiquitous, and anything can be considered a stream: variables, user inputs, attributes, caches, data structures, and so on. For example, suppose your comments on Twitter are a stream of data like a single click event, and you can listen to that stream and respond to it.
  • There are a bunch of functions that can create, combine and filter any stream. This is the magic of the functional. One stream can serve as input to another, or even multiple streams can serve as input to other streams. You can merge two streams. You can also filter a stream to get the events you’re interested in. You can map data from one stream to a new stream.
  • The main components of reactive programming are Observables, operators, and observers
  • Observable -> Operator1 -> Operator2->… ->OperatorN->Observer
  • Observables are producers of events, and observers are ultimate consumers of events. Events can be processed and converted by any number of operators
  • Because the Observer is usually executed in the main thread, it is designed to keep the code as simple as possible, only responding to events (no changes are made to events or data; all changes to events are done by the operator)

RxJava and RxAndroid

  • RxJava is an implementation of ReactiveX on the Java platform, and you can think of it as a normal Java class library.
  • RxAndroid is an extension of RxJava for the Android platform, mainly for Android development.
  • RxJava is an asynchronous development framework, and the Android system provides the Handler + Thread, AsyncTask, Context, is to solve the same problem such as runOnUiThread. So how does it compare to the asynchronous programming scheme provided by the system? Or what advantage does it have that is worth the time and effort to switch to RxJava?

It can be summed up in two words: asynchronous and concise

The main concept

Observable

Observables is responsible for issuing a series of events, which can be anything from the result of a network request to the result of complex computational processing, the structure of a database operation, the result of a file operation, etc., to the callback processing handed to the Observer after the event is executed.

An Observer

Subscribe to accept processing events

Operator(Operator)Chinese document

Responsible for various changes and processing of events

Scheduler

Provides a variety of schedulers, is RxJava can facilitate the implementation of asynchronous development

The event

The event values here are onNext (new data), onComplete (all data processing completed), onError (event queue exception)

Benefits of RxJava (why RxJava is so important for Android)

  • Easy concurrency: Make asynchronous programming simple and concise. It’s like writing synchronous code.
  • Easy thread switching
  • Simple and sophisticated exception handling: While traditional try/cache cannot handle exceptions from asynchronous neutron threads, RxJava provides a suitable error handling mechanism
  • Strong operator support, functional style, chain calls.

For example

Let’s say we have a custom view, imageCollectorView, that displays multiple images and can use addImage(Bitmap) to arbitrarily add images. Now we need the program to load the PNG images in each directory in a given directory array File[] folders and display them in imageCollectorView. Note that since the process of reading images is time-consuming, it needs to be performed in the background, whereas the display of images must be performed in the UI thread.

Directory array


File[] folders=newFile[]{...... };Copy the code

Thread implementation (Call Hell)


new Thread() {
    @Override
    public void run(a) {
        super.run();
        try{
          for (File folder : folders) {
              File[] files = folder.listFiles();
              for (File file : files) {
                  if (file.getName().endsWith(".png")) {
                      final Bitmap bitmap = getBitmapFromFile(file);
                      getActivity().runOnUiThread(new Runnable() {
                          @Override
                          public void run(a) { imageCollectorView.addImage(bitmap); }}); }}}}catch(Exception e){
          //error handling
          // Exception handling can only be done here
        }

    }
}.start();Copy the code

RxJava implementation


/ / create observables
Observable observable = Observable.create(new ObservableOnSubscribe<File>() {
            @Override
            public void subscribe(ObservableEmitter<File> e) throws Exception {
                for(File file : files) { e.onNext(file); } e.onComplete(); }});/ / create the Observer
Observer<Bitmap> observer = new Observer<Bitmap>() {
            @Override
            public void onSubscribe(Disposable disposable) {}@Override
            public void onNext(Bitmap bitmap) {
                imageCollectorView.addImage(bitmap);
            }

            @Override
            public void onError(Throwable throwable) {
              //error handling
            }

            @Override
            public void onComplete(a) {
                Log.i(TAG,"All images are shown"); }};// Process the set of events and connect consumers
observable.flatMap(new Func1<File, Observable<File>>() {// Get the files under each folder separately and combine them into an Observable
              @Override
              public Observable<File> call(File file) {
                  return Observable.from(file.listFiles());
              }
          })
          .filter(new Func1<File, Boolean>() {// Filter out all files with the PNG extension
              @Override
              public Boolean call(File file) {
                  return file.getName().endsWith(".png");
              }
          })
          .map(new Func1<File, Bitmap>() {// Get the Bitmap from the File object
              @Override
              public Bitmap call(File file) {
                  return getBitmapFromFile(file);
              }
          })
          .subscribeOn(Schedulers.io())// Specify that all Observable operators are performed in the IO thread
          .observeOn(AndroidSchedulers.mainThread())// Specify the consumer to execute in the main thread
          .subscribe(observer);// Connect the observerCopy the code

Some of you might say, aren’t you getting more code, more complex? Don’t worry, this is just the most basic version and the code will be simplified later. But even in this case, there is more code, but we can see that it is more logical and less nested.

Simplify the code

  • For an array, the create operator “from” is used to create an Observable
  • If we were only interested in the results and not the exception handling and event launch completion events, I could also replace Observer with Consumer

/ / create observables
Observable observable = Observable.from(folers);
/ / create the Observer
Consumer<Bitmap> consumer=new Consumer<Bitmap>() {
            @Override
            public void accept(@NonNull Bitmap bitmap) throws Exception { imageCollectorView.addImage(bitmap); }};// Process the set of events and connect consumers
observable.flatMap(new Func1<File, Observable<File>>() {// Get the files under each folder separately and combine them into an Observable
              @Override
              public Observable<File> call(File file) {
                  return Observable.from(file.listFiles());
              }
          })
          .filter(new Func1<File, Boolean>() {// Filter out all files with the PNG extension
              @Override
              public Boolean call(File file) {
                  return file.getName().endsWith(".png");
              }
          })
          .map(new Func1<File, Bitmap>() {// Get the Bitmap from the File object
              @Override
              public Bitmap call(File file) {
                  return getBitmapFromFile(file);
              }
          })
          .subscribeOn(Schedulers.io())// Specify that all Observable operators are performed in the IO thread
          .observeOn(AndroidSchedulers.mainThread())// Specify the consumer to execute in the main thread
          .subscribe(consumer);// Connect consumersCopy the code

RxJava chain call implementation


Observable.from(folders)
    .flatMap(new Func1<File, Observable<File>>() {
        @Override
        public Observable<File> call(File file) {
            return Observable.from(file.listFiles());
        }
    })
    .filter(new Func1<File, Boolean>() {
        @Override
        public Boolean call(File file) {
            return file.getName().endsWith(".png");
        }
    })
    .map(new Func1<File, Bitmap>() {
        @Override
        public Bitmap call(File file) {
            return getBitmapFromFile(file);
        }
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Consumer<Bitmap>() {
                @Override
                public void accept(@NonNull Bitmap bitmap) throws Exception { imageCollectorView.addImage(bitmap); }});Copy the code

RxJava + lambda implementation


Observable.from(folders)
    .flatMap(file -> Observable.from(file.listFiles())
    .filter(file -> file.getName().endsWith(".png"))
    .map( file -> getBitmapFromFile(file))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(bitmap -> imageCollectorView.addImage(bitmap));// There is no exception processing, exceptions will be thrown to the main thread, does not affect our original program crash processingCopy the code

About the use of lambda(anonymous functions, which can contain expressions and statements) in Android:

  • To test Lambda expressions, method references, and type annotations in earlier versions of Android, go to your build.gradle file and set compileSdkVersion and targetSdkVersion to 23 or lower. You still need to enable the Jack tool chain to use these Java 8 features.
  • After testing and configuration according to the official scheme, although lambda can be used, the compilation speed becomes very slow.
  • At runtime, and the project reference I tested changed the Bouncy Castle (Light Encryption and Decryption Kit) package to report a memory overflow exception, so I feel a bit shaky right now.
  • Third party open source implementation: Retrolambda
  • Of course we could have done without lambda, which would have made the code look a lot more, but since there is only one layer of nested chain calls, the logical structure is not complicated. In fact, Android Studio automatically folds this code into a lambda form for us.

Further, suppose we now need to ignore the first five and display a total of 10


Observable.from(folders)
    .flatMap(file -> Observable.from(file.listFiles())
    .filter(file -> file.getName().endsWith(".png"))

    .skip(5)
    .take(10)

    .map( file -> getBitmapFromFile(file))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(bitmap -> imageCollectorView.addImage(bitmap));// There is no exception processing, exceptions will be thrown to the main thread, does not affect our original program crash processingCopy the code

Operator Introduction

The create operation

Operator used to create an Observable

  • Create – Creates an Observable from scratch by calling the observer’s methods

    The create operator is the “root” of all create operators, which means that all other create operators end up creating observables from the create operator

  • From – Converts other objects or data structures into Observables

  • Just – transforms an object or collection of objects into an Observable that emits those objects
  • Defer – Instead of creating this Observable before the observer subscribes, create a new Observable for each observer
  • Empty/Never/Throw – Creates a special Observable with limited behavior

    Generally used for testing

  • Interval – Creates an Observable that periodically emits integer sequences

  • Range – Creates an Observable that emits a sequence of integers in a specified Range
  • Repeat – Creates an Observable that repeatedly emits specific data or data sequences
  • Start – Creates an Observable that emits the return value of a function
  • Timer – Creates an Observable that emits single data after a specified delay
Transform operation

These operators can be used to transform data emitted by an Observable

  • Map — A mapping that transforms the data emitted by an Observable by applying a function to each item in the sequence. Essentially, it executes a function on each item in the sequence, and the parameter of the function is the data item
  • Buffer – A cache, simply known as a cache, that periodically collects data from an Observable into a collection and then packs the data into a bundle rather than one at a time
  • FlatMap — Flat mapping transforms the data emitted by Observables into Observables collection, and then flattens the data emitted by these Observables into a single Observable. It can be considered as a process of expanding nested data structures.
  • GroupBy — The original Observables are divided into a collection of Observables, and the data emitted by the original Observables are grouped by Key. Each Observable emits a group of different data
  • Scan – scans, applying a function to each piece of data emitted by an Observable and emitting the values in sequence
  • Window – a Window that periodically splits data from an Observable into Observable Windows and fires them instead of one at a time. Similar to buffers, but buffers emit data, while Windows emit observables. Each Observable emits a subset of the original Observable’s data
Filtering operation

These operators are used to select data emitted by the Observable. Those that meet certain conditions are sent to the observer for processing, and those that do not are discarded directly

  • Filter – To Filter out data items that do not pass the predicate test and only fire those that do
  • Skip – To Skip the previous items of data
  • SkipLast – Skips subsequent items of data
  • Take – Only the first few items of data are retained
  • TakeLast – Only the last few items of data are retained
  • Debounce – Emits data only after it has been idle for a period of time. In layman’s terms, an operation is performed if there has been no operation for a while
  • Distinct – Deduplication: Duplicate data items are filtered out
  • ElementAt – Values that take data items at a specific location
  • First – The First item, only the First data that meets the condition is transmitted
  • IgnoreElements – Ignores all data and only keeps/terminates notifications (onError or onCompleted)
  • Last – The Last item, only the Last piece of data is transmitted
  • Sample — ThrottleFirst. Periodically emitting the latest data. This is equivalent to sampling data
Combination operation

The composition operator is used to combine multiple Observables into a single Observable

  • And/Then/When – Combines data sets emitted by two or more Observables using patterns (And conditions) And plans (Then order)
  • CombineLatest – When either Observables emits a data, combine the latest data emitted by each Observable (two Observables) with a specified function, and emit the result of that function
  • Join – Whenever one Observable emits a data item, the data emitted by two Observables is merged within the time window defined by the data item emitted by another Observable
  • Merge – Combines data emitted by two Observables into one
  • StartWith – Fires a specified data sequence or item before launching the original Observable’s data sequence
  • Switch – Converts an Observable that emits Observable sequences into an Observable that emits the most recent data emitted by each Observable
  • Zip – a package that combines data emitted by multiple Observables using a specified function and emits the result of that function as a single data
Error handling

These operators are used to recover from error notifications

  • Catch – To Catch, to continue sequence operations, to replace errors with normal data, to recover from onError notifications
  • Retry – Retries. If an Observable emits an error notification, re-subscribes to it, expecting it to terminate normally
Auxiliary operation

A set of operators that handle Observables

  • Delay – To Delay transmitting result data for a period of time
  • Do – Registers an action that takes up some Observable lifecycle events and mocks an operation
  • Materialize/Dematerialize – will launch the data and inform as launch, or vice versa
  • ObserveOn – a scheduler (worker thread) that assigns observers to observe observables
  • SubscribeOn – Specifies which dispatcher an Observable should run on
  • Serialize – Forces observables to emit data in order and function effectively
  • Subscribe – The action that an Observable performs after receiving data and notifications from it
  • TimeInterval – Converts an Observable into an Observable that takes time to emit between two data
  • Timeout – Adds a Timeout mechanism that emits an error notification if a specified period of time has elapsed without transmitting data
  • Timestamp – Adds a Timestamp to each data item emitted by an Observable
  • Using – Creates a one-time resource that exists only during the life of an Observable
Conditional and Boolean operation

These operators can be used for single or multiple data items, as well as observables

  • All – Checks whether All data items emitted by an Observable meet certain conditions
  • Amb – Given multiple Observables, only the first Observable that emits data emits all data
  • Contains – Determines whether an Observable emits a specified data item
  • DefaultIfEmpty – Emits data from the original Observable, and if the original Observable doesn’t emit data, emits a default
  • SequenceEqual – Determines whether two Observables follow the same data sequence
  • SkipUntil – discards data emitted by the original Observable until the second Observable emits a data, and then emits the rest of the original Observable’s data
  • SkipWhile – discards the data emitted by the original Observable until a particular condition is false, then emits the rest of the original Observable’s data
  • TakeUntil – emits data from the original Observable until the second Observable emits a data or notification
  • TakeWhile – emits the original Observable data until a specific condition is true, then skips the rest of the data
Arithmetic and aggregation operations

These operators can be used for entire data sequences

  • Average – calculates the Average of the data sequence emitted by an Observable and emits the result
  • Concat – connects data from multiple Observables without interleaving them
  • Count – Counts the number of data emitted by an Observable and emits the result
  • Max – Calculates and transmits the maximum value of a data sequence
  • Min – Calculates and transmits the minimum value of the data sequence
  • Reduce – Apply a function to each of the data sequences in order and return this value
  • Sum – Calculates and emits the Sum of data sequences
Join operation

Special Observables with precise, controllable subscription behavior

  • Connect – Instructs a connected Observable to start sending data to subscribers

    • A connectable Observable is similar to a normal Observable, except that it doesn’t start emitting data when it is subscribed to, but only when the Connect operator is used. With this method, you wait for all observables to subscribe to observables before launching data.
    • Connect is a method of the ConnectableObservable interface in RxJava. The Publish operator can be used to convert a normal Observable into a ConnectableObservable.
    • For example,

      
      ConnectableObservable<String> connectableObservable = Observable.just("a"."c"."d").publish();
          connectableObservable.subscribe(new Consumer<String>() {
              @Override
              public void accept(@NonNull String s) throws Exception { LogUtil.i(s); }}); LogUtil.i("subscribe end.....");
      
          Observable.timer(3, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
              @Override
              public void accept(@NonNull Long aLong) throws Exception {
                  LogUtil.i("connect method called after 3 seconds."); connectableObservable.connect(); }});Copy the code
      03-20 15:54:19. 328, 27493-27493 / me. Sunbird. React_native_demo I/x_log: RxJavaActivity. TestConnectableObservable (L: 586). subscribe end..... 03-20 15:54:22. 378, 27493-27573 / me. Sunbird. React_native_demo I/x_log: RxJavaActivity $34. Accept (L: 591). Connect method called after 3 seconds. 03-20 15:54:22.419 27493-27573/me.sunbird.react_native_demo I/x_log:RxJavaActivity$33.accept(L:582): A 03-20 15:54:22.419 27493-27573/me.sunbird.react_native_demo I/x_log:RxJavaActivity$33.accept(L:582): React_native_demo I/x_log:RxJavaActivity$33.Accept (L:582): dCopy the code
  • Publish – Converts a normal Observable to a linkable

  • RefCount – Makes a connected Observable behave like a normal Observable
  • Replay – Ensures that all observers receive the same data sequence, even if they subscribe after the Observable starts emitting data
Conversion operations
  • To – Converts an Observable To another object or data structure
  • Blocking the Observable operator
Operator decision tree

There are several main requirements

  • Create an Observable directly.
  • Combine multiple Observables
  • Perform transformations on data emitted by an Observable (transform)
  • Retrieves specific values from data emitted by an Observable (filtering operation)
  • Forwarding partial Observable values (conditional/Boolean/filter operations)
  • Evaluate data sequences emitted by an Observable (arithmetic/aggregate operations)

SchedulerChinese document

RxJava is essentially a framework for asynchronous development that allows us to be extremely flexible with thread switching. You can use the ObserveOn and SubscribeOn operators, you can have an Observable execute on a particular scheduler, ObserveOn tells an Observable to call the observer’s onNext, onError, and onCompleted methods on a particular scheduler. It instructs an Observable to perform all processing, including emission data and notifications, on a specific scheduler. The subscribeOn and observeOn operators are extremely confusing, so check out this blog to make a complete distinction between the two operators

Scheduler type The effect
Schedulers.com putation ( ) Use schedulers.io () for computing tasks, such as event loops or callback processing, not IO operations (IO operations use schedulers.io ()); The default thread count is equal to the number of processors
Schedulers.from(executor) Uses the specified Executor as the scheduler
Schedulers. Immediate ( ) Start the task immediately on the current thread
Schedulers. IO ( ) For IO intensive tasks, such as asynchronously blocking IO operations, the scheduler’s thread pool grows as needed; For normal computing tasks, use Schedulers.computation(); Schedulers.io( ) defaults to a CachedThreadScheduler, much like a new thread scheduler with a thread cache
Schedulers. NewThread ( ) Create a new thread for each task
Schedulers. Trampoline ( ) When other queued tasks complete, the current thread queues to start execution

Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                LogUtil.w("subscribe method is running in thread:" + Thread.currentThread().getName());
                observableEmitter.onNext("a");
                observableEmitter.onComplete();
            }
        }).map(new Function<String, String>() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                LogUtil.w("first map is running in thread:" + Thread.currentThread().getName());
                return s;
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .map(new Function<String, String>() {
                    @Override
                    public String apply(String s) throws Exception {
                        LogUtil.w("second map is running in thread:" + Thread.currentThread().getName());
                        return s;
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<String, String>() {
                    @Override
                    public String apply(String s) throws Exception {
                        LogUtil.w("third map is running in thread:" + Thread.currentThread().getName());
                        return s;
                    }
                })
                .observeOn(Schedulers.computation())
                .map(new Function<String, String>() {
                    @Override
                    public String apply(@NonNull String s) throws Exception {
                        LogUtil.w("fourth map is running in thread:" + Thread.currentThread().getName());
                        return s;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        LogUtil.w("consumer accept method is running in thread:"+ Thread.currentThread().getName()); }});Copy the code

After running, we can get the following results:

03-20 11:44:23. 716, 8687-8723 /? W/x_log:RxJavaActivity$27.subscribe(L:528): The subscribe method is running in the thread: 03-20 11:44:23 RxCachedThreadScheduler - 1. 717, 8687-8723 /? W/x_log:RxJavaActivity$28.apply(L:535): First map is running in the thread: 03-20 11:44:23 RxCachedThreadScheduler - 1, 721, 8687-8724 /? W/x_log:RxJavaActivity$29.apply(L:543): The second map is running in the thread: 03-20 11:44:23 RxNewThreadScheduler - 1. 726, 8687-8725 /? W/x_log:RxJavaActivity$30.apply(L:551): Third map is running in the thread: RxCachedThreadScheduler - 03-20 11:44:23. 729, 8687-8726 /? W/x_log:RxJavaActivity$31.apply(L:559): Fourth map is running in the thread: 03-20 11:44:23 RxComputationThreadPool - 1, 836, 8687-8687 /? W/x_log:RxJavaActivity$32.accept(L:567): consumer accept method is running in thread:mainCopy the code

Examples of RxJava usage scenarios

Complex data transformation

Observable.just("1"."2"."2"."3"."4"."5")/ / create observables
    .map(Integer::parseInt)// Execute the integer.parseint method on each item
    .filter(s -> s > 1)// Filter out all objects with values >1
    .distinct() // We can also pass a method to define whether two objects are equals
    .take(3)// select the first three
    .reduce((sum, item) -> sum + item) / / accumulation
    .subscribe(System.out::println);//9 prints out the final summation.Copy the code
Retrofit combines RxJava to do a network request framework

Here is not a detailed explanation, the specific introduction can see the throw line of this article, RxJava beginners have a great inspiration. It also talks about how RxJava and Retrofit can be combined to achieve cleaner code. Right

RxJava replaces EventBus for data transfer
RxBus

RxBus is not a library, but a pattern that uses the ideas of RxJava to achieve the data transfer effects of EventBus. This article describes RxBus in more detail.

square/OttoAttitude towards RxBus

This project is deprecated in favor of RxJava and RxAndroid. These projects permit the same event-driven programming model as Otto, but they’re more capable and offer better control of threading.

We have scrapped this project in favor of RxJava and RxAndroid. Both projects offer the same event-driven programming model as Otto, but they are more powerful and provide better thread control.

If you’re looking for guidance on migrating from Otto to Rx, this post is a good start.

If you are looking for a tutorial on migrating from Otto to Rx, reading this article will be a good place to start.

One network request depends on the results returned by another network request. For example, after login, the token is given to retrieve the message list.
@GET("/token")
public Observable<String> getToken(a);

@GET("/user")
public Observable<User> getUser(@Query("token") String token, @Query("userId") String userId); . getToken() .flatMap(new Func1<String, Observable<User>>() {
        @Override
        public Observable<User> call(String token) {
            return getUser(token, userId);
        })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<User>() {
        @Override
        public void onNext(User user) {
            userView.setUser(user);
        }

        @Override
        public void onCompleted(a) {}@Override
        public void onError(Throwable error) {
            // Error handling. }});Copy the code
If more than two requests are made by a colleague on the same page, the ProgressBar on the page is managed. In other words, only one ProgressBar can be displayed by two requests and the ProgressBar can disappear after all requests are completed

@GET("/date1")
public Observable<String> getDate1(a);

@GET("/data2")
public Observable<String> getData2(a). progressDialog.show(a)
Observable.merge(getData1().getData2(a)).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable disposable) {}@Override
                    public void onNext(String s) {
                      // Here is the result processing
                    }

                    @Override
                    public void onError(Throwable throwable) {
                      //error handling
                      progressDialog.dismiss();
                    }

                    @Override
                    public void onComplete(a) { progressDialog.dismiss(); }});Copy the code
Use throttleFirst to prevent button duplication

RxView.clicks(button)
    .throttleFirst(1, TimeUnit.SECONDS)
    .subscribe(new Observer<Object>() {
        @Override
        public void onCompleted(a) {
              log.d ("completed");
        }

        @Override
        public void onError(Throwable e) {
              log.e("error");
        }

        @Override
        public void onNext(Object o) {
             log.d("button clicked"); }});Copy the code
Use Debounce to do textSearch

In simple terms, debounce automatically filters out the first n-1 nodes when N nodes are too close together (i.e., when the time difference is less than the set value T). For example, when doing Baidu address association, debounce can be used to reduce frequent network requests. Avoid making associations every time you type (delete) a word

RxTextView.textChangeEvents(inputEditText)
      .debounce(400, TimeUnit.MILLISECONDS)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(new Observer<TextViewTextChangeEvent>() {
    @Override
    public void onCompleted(a) {
        log.d("onComplete");
    }

    @Override
    public void onError(Throwable e) {
        log.d("Error");
    }

    @Override
    public void onNext(TextViewTextChangeEvent onTextChangeEvent) {
        log.d(format("Searching for %s", onTextChangeEvent.text().toString())); }});Copy the code

RxJava ecological

  • Rx – Preferences – Enables SharedPreferences to support RxJava

  • RxAndroid – Android extension of RxJava

  • RxLifecycle – Helps control the lifecycle of Android applications using RxJava

  • RxBinding – RxJava binding API for Android UI controls

  • Android-ReactiveLocation -Google Play Service API wrapped in RxJava

  • Storio – RXJava-enabled database

  • Retrofit – A web request library that supports RxJava

  • Sqlbrite – A SQLite database that supports RxJava

  • RxPermissions – Android runtime permission control implemented by RxJava

  • reark -RxJava architecture library for Android

  • frodo -Android Library for Logging RxJava Observables and Subscribers.

The current situation of RxJava

  • RxJava latest version 2.0.7 (note: incompatible with 1.x version) size 2.1m
  • RxAndroid size 10 k
  • Support Java6 or above, Android2.3 or above
  • github star 22511

The future of RxJava

General data flow, powerful operators, flexible thread scheduling, simple and perfect exception handling mechanism, functional programming and other features, lay the powerful position of RxJava. The Android system is full of asynchronous requests, such as network requests, file reads and writes, database queries, system services or third-party SDK services, etc. These asynchronous requests are time-consuming and need to be executed in a non-UI thread, and UI changes must be executed in the main thread. If we nested multiple asynchronous implementations, it would clutter up our code. Through the powerful and universal asynchronous processing mechanism provided by RxJava, we can make our code logic clearer and easier to maintain later. In addition, the RxJava ecosystem is becoming larger and larger. In my opinion, in the future, all system services, third-party libraries and third-party service SDKS involving asynchronous operations will be provided to us in the form of Observables or class Observables, instead of transferring listeners one after another like now.

The resources

  • reactivex.io
  • Chinese translation of ReactiveX documents
  • Introduction to responsive programming
  • RxJava for Android developers
  • Best practices for RxJava combined with Retrofit
  • Awesome-RxJava
  • Use responsive programming in Android
  • SubscribeOn and ObserveOn

Sharing tools

Zeplin (Software Demonstration)
  • Convenient renderings management
  • New file, modify file prompt
  • Automatic measurement
  • Marked with comments
  • Support for PohtoShop and Sketch
  • The first item is free
Charles (Software Demo)
  • Simple already used, powerful function
  • Focus a domain name under the request, easy to find
  • Modify the parameters of a request and request again for easy debugging
  • A variety of well-formed response parsing
  • Copy out cURL format request, convenient transfer of anyone request simulation