Android開源框架集合分享-響應式函數編程Rx

       今天來給大家介紹當下比較流行的響應式函數編程,以下是整理和蒐集整理的關於Rx的一些資料。響應式函數編程

確實是一種對新入行的人來說是一種新穎而又高效的編程方式。但是不建議新手採用這種方法進行立項,其中的牽扯到

觀察者模式,訂閱者模式還得等看過一定的算法和設計模式之後,才能理解的恰如其分,使用起來也可以得心應手,不過

在學習基礎的時候,理解和練習一些小的demo,對學習設計模式還是很有幫追的。今天介紹的實際上只有只有一種,就是

RxJava與RxAndroid,當然現在也有很多框架,像上幾篇提高的網絡請求OkGo都支持Rx的擴展,基於此給大家分享一下。

5、響應式函數編程Rx(Reactive Extensions)

主頁:https://github.com/ReactiveX/RxJava

中文資料:(這是一些大神分享一些學習的資料,參照的學習,確實英語有點尷尬了)

https://github.com/lzyzsd/Awesome-RxJava

https://www.zhihu.com/question/35511144

含義:

      RxJava 的異步實現,是通過一種擴展的觀察者模式來實現的。

      觀察者模式面向的需求是:A 對象(觀察者)對 B 對象(被觀察者)的某種變化高度敏感,需要在 B 變化的一瞬間做出反應

用途:

     異步操作

     在程序邏輯異常複雜的情況下,仍然可以讓代碼的邏輯保持簡潔

配置: 添加依賴:

compile'io.reactivex.rxjava2:rxandroid:2.0.1'

compile'io.reactivex.rxjava2:rxjava:2.1.0'

如果結合Retrofit使用,需要添加以下依賴

compile 'com.squareup.retrofit2:retrofit:2.0.1'

compile 'com.squareup.retrofit2:converter-gson:2.0.1'

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'

基本的理解和用法

1.被觀察者: Observable

     作用: 決定什麼時候觸發事件以及觸發怎樣的事件

創建方法:

   Observable.just(T...) 參數爲單個的

   Observable.from(T[]) / Observable.from(Iterable)  參數爲數組或Iterable

2.觀察者: Observer

   作用: 當事件觸發的時候將有怎樣的行爲

   實現類有Observer / Subscriber

3.訂閱: subscribe

   作用: 把Observable和Observer關聯起來

   方法:

  observable.subscribe(observer);

  observable.subscribe(subscriber);

4.事件

  onNext():普通事件

  onCompleted():事件隊列完結

  onError(): 事件隊列異常

  需要注意的是onCompleted()和onError()是互斥的.調用了其中一個就不應該觸發另一個.

5.測試程序

      現有一個數組 String[] arr ={"afdsa", "bfdsa", "cfda"}, 把其中以字母"a"開頭的字符串找出來並加上"from Alpha",最後打印出新的字符串的長度

   private void simpleDemo() {

      String[] arr = {"afdsa", "bfdsa", "cfda"};

      Observable

                .from(arr)

                .filter(new Func1() {

                     @Override

                     public Boolean call(String s) {

                     return s.startsWith("a");

                    }

                 })

                .map(new Func1() {

                     @Override

                     public String call(String s) {

                          return s + " from Alpha";

                              }

                       })

                     .subscribe(new Action1() {

                     @Override

                     public void call(String s) {

                          System.out.println("Rxjava:" + s.length());

                              }

                     });

                     for (int i = 0; i < arr.length; i++) {

                          String temp = arr[i];

                          if (temp.startsWith("a")) {

                              temp += " from Alpha";

                              System.out.println("Normal:" + temp.length());

                         }

                     }

 由指定的一個 drawable 文件 id 取得圖片,並顯示在 ImageView 中,並在出現異常的時候打印 Toast 報錯

private void simpleDemo() {

           final int drawID = R.mipmap.ic_launcher;

                 Observable

                          .create(new Observable.OnSubscribe() {

                          @Override

                          public void call(Subscriber subscriber) {

                          Drawable drawable = getResources().getDrawable(drawID);

                          subscriber.onNext(drawable);

                          subscriber.onCompleted();

                       }

                })

                         .subscribe(new Observer() {

                         @Override

                         public void onCompleted() {

                          }

                         @Override

                         public void onError(Throwable e) {

                            Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();

                          }

                         @Override

                         public void onNext(Drawable drawable) {

                            imageView.setImageDrawable(drawable);

                         }

               });

      }

6.Scheduler(調度器)

     作用: 控制線程.指定某一段代碼在那個線程裏運行.

     在不指定線程的情況下, RxJava 遵循的是線程不變的原則,即:在哪個線程調用 subscribe(),就在哪個線程生產事件;在哪個線程生產事件,就在哪個線程消費事件。如果需要切換線程,就需要用到 Scheduler (調度器)。

    在RxJava 中,Scheduler ——調度器,相當於線程控制器,RxJava 通過它來指定每一段代碼應該運行在什麼樣的線程。RxJava 已經內置了幾個 Scheduler ,它們已經適合大多數的使用場景:

    內置的Scheduler:

    Schedulers.immediate(): 直接在當前線程運行,相當於不指定線程。這是默認的 Scheduler。

    Schedulers.newThread(): 總是啓用新線程,並在新線程執行操作。

    Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的 Scheduler。行爲模式和 newThread() 差不多,區別在於 io() 的內部實現是是用一個無數量上限的線程池,可以重用空閒的線程,因此多數情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創建不必要的線程。

    Schedulers.computation(): 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小爲 CPU 核數。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。

    AndroidSchedulers.mainThread(): Android專用,它指定的操作將在 Android 主線程運行。

    指定線程的方法:

    Observable.subscribeOn():指定 subscribe() 所發生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產生的線程

    Observable.observeOn():指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。

7.數據變換

  作用: 就是將事件序列中的對象或整個序列進行加工處理,轉換成不同的事件或事件序列

Observable.map:  一對一的轉換

  private void simpleDemo() {

             Observable

                       .just(R.mipmap.ic_launcher)

                       .map(new Func1() {

                        @Override

                        public Drawable call(Integer integer) {

                            return getResources().getDrawable(integer);

                              }

                        })

                       .subscribe(new Action1() {

                        @Override

                        public void call(Drawable drawable) {

                            imageView.setImageDrawable(drawable);

                                  }

                            });

                     }

 Observable.flatMap: 一對多的轉換

       public class Course {

               private String name;

               private int id;

               public Course(String name, int id) {

                   this.name = name;

                   this.id = id;

                  }

               public String getName() {

                   return name;

                  }

               public void setName(String name) {

                   this.name = name;

                  }

              public int getId() {

                  return id;

                 }

             public void setId(int id) {

                 this.id = id;

                 }

             }

   public class Student {

        private String name;

        private ArrayList courses;

        public Student(String name, ArrayList courses) {

              this.name = name;

             this.courses = courses;

        }

       public String getName() {

            return name;

        }

       public void setName(String name) {

           this.name = name;

         }

      public ArrayList getCourses() {

          return courses;

        }

     public void setCourses(ArrayList courses) {

         this.courses = courses;

       }

    }

    private void student() {

          Course yuwen = new Course("語文", 1);

          Course shuxue = new Course("數學", 2);

          Course yingyu = new Course("英文", 3);

          Course lishi = new Course("歷史", 4);

          Course zhengzhi = new Course("政治", 5);

          Course xila = new Course("希臘語", 6);

          ArrayList course1 = new ArrayList<>();

          course1.add(yuwen);

          course1.add(shuxue);

          course1.add(yingyu);

          course1.add(lishi);

          course1.add(zhengzhi);

          course1.add(xila);

          Student zhangsan = new Student("zhangsan", course1);

          Observable.just(zhangsan)

                                   .flatMap(new Func1>() {
 
                                   @Override

                                   public Observable call(Student student) {

                                      return Observable.from(student.getCourses());

                                    }

                                   }).subscribe(new Action1() {

                                   @Override

                                   public void call(Course course) {

                                       System.out.println(course.getName());

                                          }

                                    });
                      }

8.和Retrofit一起使用

1.添加依賴:

compile 'com.squareup.retrofit2:retrofit:2.0.1'

compile 'com.squareup.retrofit2:converter-gson:2.0.1'

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'

2.利用http://www.jsonschema2pojo.org創建數據模型

3.創建REST API 接口.注意此時返回的不能是Call而是Observable.示例代碼:

public interface LocationInterface {

          // http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.23

          @GET("/service/getIpInfo.php")

         public Observable getLocation(@Query("ip") String ip);

  }

4.創建Retrofit對象,發起請求.注意此時Retrofit需要添加addCallAdapterFactory.示例代碼:       

       Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE2)

                                                .addConverterFactory(GsonConverterFactory.create())

                                                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())

                                                .build();

        LocationInterface locationInterface = retrofit.create(LocationInterface.class);

        Observable location = locationInterface.getLocation("8.8.8.8");

        location

                .subscribeOn(Schedulers.io())

                .map(new Func1() {

                   @Override

                    public String call(Location location) {

                        return location.getData().getCountry();

                       }

              })

               .observeOn(AndroidSchedulers.mainThread())

               .subscribe(new Action1() {

               @Override

                  public void call(String s) {

                       textView.setText(s);
                     }
           });

        以上就是這次整理的內容,整體來說就一個框架的內容,就是響應式編程的介紹,不夠我對這個東西算不上是熟悉的,因爲確實沒有在正式的項目中使用過這個東西,但從平常的測試實踐中感覺這個確實對設計和解耦非常有幫助,不過自從看了kotlin之後,覺得這個東西就稍微差了一點點,這個東西仁者見仁智者見智吧,希望有研究過的小夥伴兒看一下,有什麼不對的地方及時的指正,一起分享學習一下。

簡書地址:https://www.jianshu.com/p/9dec3c8b9bfd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章