Introduction to RxJava

Keywords: network Programming Mobile Android

When I encounter new knowledge, I usually learn quickly from three aspects (what-why-why-why-why, what problems it solves and how-how-how). Then I will analyze from these three aspects.

  • 1.what?

    • What exactly is RxJava? Let's skip the official obscure pursuit of precise definitions. In fact, RxJava beginners only need to grasp two points:

      • With observer mode and asynchronism, you can be proficient in RxJava. Asynchronism does not need to be explained too much here, because there is not much depth in concept and usage. It's probably the multithreading, threading switching stuff that you can think of in your mind. I'll explain its usage later. Ultimately, it's a library for asynchronous operations.
    • Let's first make the observer mode clear: "Press the switch, the lamp is on."
      In this event, the lamp acts as the observer, the switch acts as the observer, and the lamp observes the state of the switch through the wire and makes corresponding treatment.

      • The switch (the observee) as the producer of the event (production "on" and "off" these two events), is active, is the starting point of the whole process of turning on the light.
      • The desk lamp (the observer) is passive and the end of the whole process of turning on the light as the event handler (dealing with the two events of "light on" and "light off".
      • Between the starting point and the end point, that is, the process of event transmission can be processed, filtered, transformed, merged and so on.
  • 2.why?

    • Simplicity does not mean the simplicity in the amount of code, but the simplicity in logic. As the logic of the program becomes more and more complex, it can still remain simple.
  • 3.how?

    • RxJava also builds its own program logic based on the observer pattern, which is to build Observable and Observer/Subscriber, and then establish the subscription relationship between them (like that wire, which connects the desk lamp and switch) to realize the observation. In the process of event transmission, events can also be handled in a variety of ways.

    • Usage

  • Simple use
private void helloWorldSimple() {
        //Create a consumer who accepts string s
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, "accept " + s);
            }
        };

        //The observee issues Hello World and designates the consumer of the event as consumer
        //From the code point of view, the observer subscribes to the observer. Why is that so? In our opinion, the consumer subscribes to the observer.
        //This is written to ensure the style of streaming API calls (I understand as chain programming, as follows)
        //Since the observer produces events, which are the starting point of events, the first step is to create the observer by using Observable as the principal call to generate events.
        // To ensure that the flow API invocation rules, Observable is directly used as the sole invocation subject and is invoked along the way.
        Observable.just("hello world").subscribe(consumer);
    }
  • Upgrade use
private void helloWorldComplex() {
        //observer can see the full version of comsumer
        Observer<String> observer = new Observer<String>() {

            //Callback the subscribe method when Observable calls it
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "onSubscribe ");
            }

            @Override
            public void onNext(String value) {
                Log.d(TAG, "onNext " + value);
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError ");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete ");
            }
        };

        Observable.just("hello world").subscribe(observer);
    }
  • Advanced use
private void helloWorldHard() {
        //Create an observer
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "onSubscribe ");
            }

            @Override
            public void onNext(String value) {
                Log.d(TAG, "onNext " + value);
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError ");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete ");
            }
        };

        //Create an Observed Person
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("hello world");  //Call the onnext method of the observer
                e.onComplete();
            }
        });

        observable.subscribe(observer);
    }
  • Here's an introduction to RxJava operators

    • Transform map operator
private void mapDemo() {
        //Converting path strings to pictures
        String imagUrl = "http://192.168.18.45:8080/GooglePlayServer/image?name=app/com.renren.mobile.android/screen0.jpg";

        Observable.just(imagUrl)
                .subscribeOn(Schedulers.newThread())   //Specifies the thread environment to be executed by the observer, and executes network requests in sub-threads
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String s) throws Exception {
                        return createBitmap(s);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())  //Switch to the main thread to execute onNext() update ui
                .subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Bitmap value) {
                        Log.d(TAG, "onNext ");
                        //display picture
                        mImage.setImageBitmap(value);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete ");
                    }
                });
    }

    /**
     * Getting bitmap Objects by Using this Method
     * Network requests are time-consuming operations and need to complete thread scheduling in RxJava re-coding in sub-threads
     *
     * @param s imagurl
     * @return Bitmap
     */
    private Bitmap createBitmap(String s) {
        try {
            URL url = new URL(s);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            if (connection.getResponseCode() == 200) {
                InputStream inputStream = connection.getInputStream();
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
  • Screening filter operator
private void filterDemo() {
        //Consumer can be seen as a streamlined observer
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, "accept " + s);  //Here the observer receives the steamed buns
            }
        };

        Observable.just("Steamed stuffed bun", "Steamed buns", "Rice porridge")
                .filter(new Predicate<String>() {
                    @Override
                    public boolean test(String s) throws Exception {
                        return s.equals("Steamed stuffed bun");  //Only steamed buns are allowed to pass the test
                    }
                })
                .subscribe(consumer);
    }
  • flatmap can accomplish data type conversion and processing in a chain way
private void flatmapDemo() {
        //Travel through each student in each class in the school, in the same way as before.
        //        for (int i = 0; i < 3; i++) {
        //            for (int j = 0; j < 3; j++) {
        //                for (int k = 0; k < 3; k++) {
        //                    Pseudo code
        //                }
        //            }
        //        }

        //Such code is poorly readable, and the more complex the data, the harder it is to read.

        //Traveling through all the students in all groups of each class in the school
        //With this approach, no matter how many layers there are, the readability of the code does not become complicated.
        Observable.fromIterable(new School().mClasses)
                .flatMap(new Function<Class, ObservableSource<Group>>() {
                    @Override
                    public ObservableSource<Group> apply(Class aClass) throws Exception {
                        Log.d(TAG, "apply " + aClass.toString());
                        return Observable.fromIterable(aClass.group);
                    }
                })
                .flatMap(new Function<Group, ObservableSource<Student>>() {
                    @Override
                    public ObservableSource<Student> apply(Group group) throws Exception {
                        Log.d(TAG, "apply " + group.toString());
                        return Observable.fromIterable(group.mStudents);
                    }
                }).subscribe(new Observer<Student>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Student value) {
                Log.d(TAG, "onNext " + value.toString());
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

    }

Posted by bokehman on Wed, 03 Apr 2019 13:30:30 -0700