RxJava極簡學習(四個簡單例子)

RxJava

提到Rxjava最多人都是用來處理,線程調度,回調地獄,加上Retrofit又支持Rxjava,所以大部分開發者都只會在請求網絡和需要切換線程的時候用到Rxjava,其實它有一個最重要的特性,它可以讓數據的流向更加直觀,代碼更清晰。

舉個栗子

比如說一個龐大的項目,一個事件傳遞的整個過程可能要經歷很多方法,方法套方法,每個方法的位置七零八落,一個個方法跳進去看,跳過去跳過來很容易把腦袋弄暈,不夠直觀。但是Rxjava可以把所有邏輯用鏈式加閉包的方式呈現,做了哪些操作,誰在前誰在后非常直觀,邏輯清晰,維護就會非常輕松。就算不是你寫的你也可以很快的了解,你可以把它看作一條河流,整個過程就是對里面的水流做進行加工。懂了這個特性我們才知道在復雜的邏輯中運用Rxjava是多么的重要。

Gradle添加依賴

要在Android中使用RxJava2, 先添加Gradle配置。

compile "io.reactivex.rxjava2:rxjava:2.0.7"
compile "io.reactivex.rxjava2:rxandroid:2.0.1"

一個簡單實例(分別創建被觀察者,觀察者和兩種對象進行關聯)


  //創建被觀察者
 Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                //調用觀察者的回調
                emitter.onNext("我是");
                emitter.onNext("RxJava");
                emitter.onNext("簡單示例");
                emitter.onError(new Throwable("出錯了"));
                emitter.onComplete();
            }
        });

        //創建觀察者
        Observer<String> observer = new Observer<String>() {

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

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

            //onSubscribe()方法是最先調用的
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG,"subscribe");
            }

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

        //注冊,將觀察者和被觀察者關聯,將會觸發OnSubscribe.call方法
        observable.subscribe(observer);

運行結果:

Observable是被觀察者,創建后傳入一個OnSubscribe對象,當Observable(觀察者)調用subscribe進行注冊觀察者時,OnSubscribe的call方法會觸發。
ObservableEmitter: Emitter 是發射器的意思,它可以發出三種類型的事件,與之對應的。
Observer有三個回調方法:

  • onNext:接受到一個事件
  • onCompleted:接受完事件后調用,只會調用一次
  • onError :發生錯誤時調用,并停止接受事件,調用一次

注:onCompleted和onError不會同時調用,只會調用其中之一

另一個簡單實例(訪問網絡時,通過RxJava來進行快捷的主線程和子線程切換)


protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView tv_return = (TextView) findViewById(R.id.tv_return);
        //創建被觀察者
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                emitter.onNext(getResponse());
            }
        });

        //創建觀察者
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String mResponse) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                tv_return.setText(mResponse);
            }
        };
       //subscribeOn() 指定的是發送事件的線程, observeOn() 指定的是接收事件的線程.
        observable.subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);

    }
    //使用okhttp訪問網上提供的接口,由于是同步get請求,需要在子線程進行
    private String getResponse() {
        String url = "http://v.juhe.cn/weather/index?cityname=%E6%9D%AD%E5%B7%9E&dtype=&format=&key=7970495dbf33839562c9d496156e13cc";
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response;

        try {
            response = client.newCall(request).execute();
            return response.body().string();
        } catch (IOException e) {
            return "error";
        }
    }

在RxJava中, 已經內置了很多線程選項供我們選擇, 例如有

  • Schedulers.io() 代表io操作的線程, 通常用于網絡,讀寫文件等io密集型的操作
  • Schedulers.computation() 代表CPU計算密集型的操作, 例如需要大量計算的操作
  • Schedulers.newThread() 代表一個常規的新線程
  • AndroidSchedulers.mainThread() 代表Android的主線程
    這些內置的Scheduler已經足夠滿足我們開發的需求, 因此我們應該使用內置的這些選項,在RxJava內部使用的是線程池來維護這些線程,所有效率也比較高。

第三個簡單實例(類型變換操作)


RxJava提供了類型變換操作,像上面的發送網絡請求事件,得到網絡請求數據,傳遞和接收的都是字符串。
而RxJava中的map操作符可以對事件進行處理,比如發送網絡請求事件,通過map處理后,可以接收到網絡請求的字符串的字節數,如下所示。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView tv_return = (TextView) findViewById(R.id.tv_return);
        //創建被觀察者
        Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                emitter.onNext(getResponse());
            }
        //通過map操作符對數據進行中間處理
        }).map(new Function<String, Integer>() {
            @Override
            public Integer apply(@NonNull String response) throws Exception {
                return response.length();
            }
        });
        //創建觀察者
        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                tv_return.setText("字數:"+integer);
            }
        };
        //綁定,指定線程
        observable.subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);

    }

第四個簡單實例(鏈式操作)


而RxJava一個引以為豪的地方就是它的鏈式操作了,可以把被觀察者和觀察者串起來。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView tv_return = (TextView) findViewById(R.id.tv_return);
        
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                emitter.onNext(getResponse());
            }
        }).map(new Function<String, Integer>() {
            @Override
            public Integer apply(@NonNull String response) throws Exception {
                return response.length();
            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(@NonNull Integer integer) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                tv_return.setText("字數:" + integer);
            }
        });
    }

這里是項目地址 其實也沒啥東西

喜歡的同學可以點個贊

參考

https://xiaobailong24.me/2017/03/18/Android-RxJava2.x/
http://www.lxweimin.com/p/6fd8640046f1

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 我從去年開始使用 RxJava ,到現在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy閱讀 5,570評論 7 62
  • 最近項目里面有用到Rxjava框架,感覺很強大的巨作,所以在網上搜了很多相關文章,發現一片文章很不錯,今天把這篇文...
    Scus閱讀 6,900評論 2 50
  • 前言我從去年開始使用 RxJava ,到現在一年多了。今年加入了 Flipboard 后,看到 Flipboard...
    占導zqq閱讀 9,203評論 6 151
  • 龜二田七桑: 空氣有點涼,請不要感冒。 我猜你還在旅途中。很遺憾我無從得知你的郵編和地址,我唯一能做的就是,封好信...
    龜二田七不吃魚閱讀 191評論 0 0
  • “怎么又是你?” 聽到聲響,少年猛地轉身,手上一把精致的手槍,差點走火。 “我…我就是想看看你是怎么獵殺妖怪的?!?..
    林望笙閱讀 438評論 2 3