The Era of Android Responsive Programming-RxJava

Keywords: Android Programming github Retrofit less

Personal blog CoorChice,https://chenbingx.github.io/ The latest article will be published CoorChice's blog Welcome to explore!
Meanwhile, by searching for the Wechat Public Number CoorChice or scanning the two-dimensional code at the end of the article, you can pay attention to my Wechat Public Number. At the same time, articles will be sent to Wechat Public Number as a priority to remind you of fresh articles.

Official Chinese Documents

Course

1. Why Responsive Programming Should Be Used

1. Although the amount of code in response programming is larger than that in common thread processing, the outstanding feature of response programming is that it is more in line with people's logical thinking and easier to understand.
2. Responsive programming is designed to handle thread work. It has an Observer on standby, ready to receive data sent by Observable.
3. Responsive programming code can be executed step by step in sequence.

II. Preparatory Concept

1.Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Subscriber Sub
Elephants can be an asynchronous task.
2.Observable observable object, an asynchronous task can be regarded as an observable object. The observable objects are divided into hot and cold:
Hot observable objects can emit data as soon as they are created, so Observer, the observer who subscribes to them, may miss some data because they are created later.
Cold observable objects need to wait until an observer observes them before they begin to emit data.
There is also a special DZ Observable, which is of connectable type and only opens after the connect() method is called.
Start transmitting data.
3.Subject is a very special type, which is equivalent to a bridge. It can be said that it is both an Observer and an Observer.
Observable.
4.Scheculer scheduler for specifying worker threads. SubscribeOn() is used to specify logical threads for observers and ObserveOn() is used to specify logical threads for subscribers.

  • When neither is specified, it works in the current thread.
  • When only SubscribeOn() is specified, it all works in this thread.
  • When ObserveOn() is specified, the observer runs on the default thread and the subscriber runs on the specified thread.

Operator

I. Creating Operators

  • create: create observable objects from scratch.
Log.e("MainActivity", " -> initData: " + Thread.currentThread().getName());
    //Creating Observers Using the Create Operator
    Observable.create(new Observable.OnSubscribe<Integer>() {
      //Logical Processing Before Launching
      @Override
      public void call(Subscriber<? super Integer> observer) {
        try {
          if (!observer.isUnsubscribed()) {
            for (int i = 1; i < 3; i++) {
              observer.onNext(i);
              Thread.sleep(1000);
              Log.e("MainActivity", " -> call: " + Thread.currentThread().getName());
            }
            observer.onCompleted();
          }
        } catch (Exception e) {
          observer.onError(e);
        }
      }
    } )
      //Logical threads that specify observers
      //.subscribeOn(Schedulers.newThread())
      //The logical thread that specifies the subscriber works on the same thread as subscribeOn() if not specified. If neither is specified, it works in the current thread.
      .observeOn(Schedulers.io())
      //Observable Emission Data
      .subscribe(
        //Create Subscribers
        new Subscriber<Integer>() {
      @Override
      public void onNext(Integer item) {
        System.out.println("Next: " + item);
        Log.e("MainActivity", " -> onNext: " + Thread.currentThread().getName());
      }

      @Override
      public void onError(Throwable error) {
        System.err.println("Error: " + error.getMessage());
      }

      @Override
      public void onCompleted() {
        System.out.println("Sequence complete.");
      }
    });
  • from: Create observable objects through a collection.
List<String> data = new ArrayList<>();
    data.add("1");
    data.add("2");
    data.add("3");
    // Converting a collection into data for sequential transmission
    Observable.from(data)
        // Specify observer worker threads
        .subscribeOn(Schedulers.newThread())
        // Specify Subscriber Work Threads
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            s -> {
              Log.e("MainActivity", " ->Action1 call: " + s);
              Log.e("MainActivity", " -> Action1 call: thread" + Thread.currentThread());
            },
            throwable -> {
              Log.e("MainActivity", " ->Action1-Throwable call: " + throwable);
              Log.e("MainActivity", " -> Action1-Throwable call: thread" + Thread.currentThread());

            },
            () -> {
              Log.e("MainActivity", " ->Action0 call: ");
              Log.e("MainActivity", " -> Action0 call: thread" + Thread.currentThread());
            });
  • Just: Similar to from, just is specified in ().
    Observable.just(1, "3", true) // Send three different types of data sequentially
        // Subscriber's Work Threads
        .observeOn(Schedulers.newThread())
        // Subscribe
        .subscribe(
            // To create a subscriber, the paradigm is a serializable object.
            new Subscriber<Serializable>() {
              @Override
              public void onCompleted() {

            }

              @Override
              public void onError(Throwable e) {

            }

              @Override
              public void onNext(Serializable serializable) {
                if (serializable.equals(1)) {
                  Log.e("MainActivity", " -> onNext: int = " + serializable.toString());
                }
                if (serializable.equals("3")) {
                  Log.e("MainActivity", " -> onNext: String = " + serializable.toString());
                }
                if (serializable.equals(false)) {
                  Log.e("MainActivity", " -> onNext: boolean = " + true);
                }
              }
            });
//Output results:
MainActivity:  -> onNext: int = 1
MainActivity:  -> onNext: String = 3
  • timer: Create an observer that emits 0 after a specified time.
Observable.timer(2, TimeUnit.SECONDS) //Create an observer with a delay of 2s through timer, which emits a 0
      //Specify Subscriber's Work Threads
      .subscribeOn(Schedulers.newThread())
      //Subscribe and create subscribers
      .subscribe(new Subscriber<Long>() {
      @Override
      public void onCompleted() {

      }

      @Override
      public void onError(Throwable e) {

      }

      @Override
      public void onNext(Long aLong) {
        Log.e("MainActivity", " -> onNext: along = " + aLong);

      }
    });

Transform operator

The transformation operator can process the transmitted data during the transmission process.

  • map: The initial data can be transformed once before the launch of Observable through the Func1 interface.
    Observable.just(
        "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1503/17/c2/3974265_1426551589288_mthumb.jpg")
        .map(s -> { // The map operator is used here to convert String-type data into Bitmap-type data and continue to pass it down.
          try {
            // Download pictures
            URL url = new URL(s);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.setConnectTimeout(5000);
            conn.connect();
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
              InputStream is = conn.getInputStream();
              byte[] bytes = new byte[1024];
              ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
              int length = 0;
              while ((length = is.read(bytes)) != -1) {
                byteBuffer.write(bytes, 0, length);
                byteBuffer.flush();
              }
              byte[] bmpBytes = byteBuffer.toByteArray();
              Log.e("MainActivity", " -> initData: byte.size = " + bmpBytes.length);
              return BitmapFactory.decodeByteArray(bmpBytes, 0, bmpBytes.length);
            }

          } catch (MalformedURLException e) {
            e.printStackTrace();
          } catch (IOException e) {
            e.printStackTrace();
          }
          return null;
        })
        .map(BitmapDrawable::new) // Here again, Bitmap-type data is converted to Drawable downstream
        .subscribeOn(Schedulers.io()) // Specify observer worker threads
        .observeOn(AndroidSchedulers.mainThread()) // Specify Subscriber's Work Threads
        // Subscribe
        .subscribe(
            // Create Subscribers
            new Subscriber<Drawable>() {
              @Override
              public void onCompleted() {

            }

              @Override
              public void onError(Throwable e) {

            }

              @Override
              public void onNext(Drawable drawable) {
                displayImage.setImageDrawable(drawable);
              }
            });

  • flatMap: Functions are similar to map, but it returns an Observable <Conversion Type>.
    APIClient.getArticles()
        // This method is called before calling OnNext(), where OnNext() is called by Retrofit.
        .doOnNext(articles -> {
          Log.e("MainActivity", " -> initData: itemsSize = " + articles.items.size());
          articles.items.remove(0);
        })
        // Create a new Observable with the results returned by the previous Observable
        .flatMap(articles -> Observable.from(articles.items)) // Here we use the from method to create Observable
        // Specifies the recipient's worker thread
        .observeOn(AndroidSchedulers.mainThread())
        // Launched to Subscribers
        .subscribe(
            // Create Subscribers
            new Subscriber<Articles.ItemsTestBean>() {
              @Override
              public void onCompleted() {

            }

              @Override
              public void onError(Throwable e) {

            }

              @Override
              public void onNext(Articles.ItemsTestBean itemsTestBean) {
                Log.e("MainActivity", " -> onNext: item " + i++ + " = " + itemsTestBean.id);
              }
            });

Filter operator

  • Filter: Through Func1 interface to filter out incompatible data from data sources.
Observable.just(1,2,3,4,5)
    //Filter out data less than 4 and emit them
    .filter(new Func1<Integer,Boolean>() {
        @Override
        public Boolean call(Integer item){
            retrun (item<4);
        }
    }).subscribe(new Subscriber<Integer> (){
         @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });
  • First: Only the first data is emitted, or the first data filtered out.
Observable.just(1,2,3,4,5)
    //Filter out data larger than 4, and transmit only the first data
    .first(new Func1<Integer,Boolean>() {
        @Override
        public Boolean call(Integer item){
            retrun (item>4);
        }
    }).subscribe(new Subscriber<Integer> (){
         @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });
  • take: Only the first few data are sent.
Observable.just(1,2,3,4,5)
    //Only the first three data are transmitted
    .take(3)
    .subscribe(new Subscriber<Integer> (){
         @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });
CoorChice's Public Name

Posted by pbsperry on Fri, 25 Jan 2019 15:18:14 -0800