RxAndroid學習筆記

一,什麼是Rx

1.Rx的基本介紹:Rx是響應式編程的意思,本質是觀察者模式,是以觀察者(Observer)和訂閱者(Subscriber)爲基礎的異步響應方式。

(1)縮寫:ReactiveX時Reactive Extensions的縮寫,一般簡寫爲Rx

(2)定義:Rx = Observables + LINQ + Schedulers.       LINQ---語言集成查詢

(3)突破:ReactiveX不僅僅是一個編程接口,它是一種編程思想的突破,它影響了許多其它的程序庫和框架以及編程語言。

(4)Rx庫支持.Net,JavaScript,C++,常用有RxJava, RxJS,  rx.NET

2.Rx模式以及優點:

<1>使用觀察者模式:

(1)創建:Rx可以方便的創建事件流和數據流

(2)組合:Rx使用查詢方式的操作符組合和變換數據流

(3)監聽:Rx可以訂閱任何可觀察的數據流並執行操作

<2>簡化代碼:

(1)函數式風格:對可觀察數據流使用無副作用的輸入輸出函數,避免了程序裏錯綜複雜的狀態

(2)簡化代碼:Rx的操作符通常可以將複雜的難題簡化爲很少的幾行代碼

(3)異步錯誤處理:傳統的try/catch沒辦法處理異常計算,Rx提供了合適的錯誤處理機制

(4)輕鬆使用併發:Rx的Observables和Schedulers讓開發者可以擺脫底層的線程同步和各種併發問題

3.Rx提供了什麼

(1)Rx提供了一些列的操作符,你可以使用它們來過濾(filter)、選擇(select)、變換(transform)、結合(combine)和組合(compose)多個Observable,

這些操作符讓執行和複合變得非常高效

(2)我們可以把Observable當做Iterable的推送方式的等價物,使用Iterable,消費者從生產者那拉取數據,線程阻塞直至數據準備好。

使用Observable,在數據準備好時,生產者將數據推送給消費者。數據可以同步或異步的到達,這種方式更靈活。


二,初始RxJava:

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

2.RxJava的四個基本概念:Observable(被觀察者)、Observer(觀察者)、subscrible(訂閱)、事件。

(1)Observable和Observer通過subscrible()方法實現訂閱關係,從而

Observable可以在需要的時候發出事件來通知Observer.

3.RxJava的基本實現:

(1)創建Observer

Observer即觀察者,它決定事件觸發的時候有怎樣的行爲。

RxJava中的Observer接口的實現方式。

(2)創建Observable

Observable即被觀察者,它決定什麼時候觸發事件以及觸發怎樣的事件。

RxJava使用create()方法來創建一個Observable,併爲它定義事件觸發規則

(3)Subscribe(訂閱)

創建了Observable和Observer之後,再創建subscribe()方法將他們聯結起來,整條鏈子就可以工作了

4,使用例子:

第一個例子:自定義接口實現:

(1)創建觀察者接口:定義監聽的方法

public interface Watcher {
    //通過update()方法監聽到狀態的通知
    public void update(String str);
}
(2)創建被觀察者接口:提供3個方法,添加觀察者,異常觀察者,通知提醒所以的觀察者

public interface Watched {
    //添加觀察者
    public void addWatcher(Watcher watcher);
    //移除觀察者
    public void removeWatcher(Watcher watcher);
    //提醒所以的觀察者
    public void notifyWatchers(String str);

}
(3)創建實現觀察者接口的觀察者類:

public class ConcreteWatcher implements Watcher {
    @Override
    public void update(String str) {

        //打印出被觀察者的消息的變化
        System.out.println(str);
    }
}
(4)創建實現被觀察者接口的被觀察者類:用ArrayList來實現多個觀察者對象的監聽狀況

public class ConcreteWatched implements Watched {

    //創建List集合
    private List<Watcher> list = new ArrayList<>();

    @Override
    public void addWatcher(Watcher watcher) {
        //添加觀察者對象
        list.add(watcher);

    }

    @Override
    public void removeWatcher(Watcher watcher) {
        //移除觀察者對象
        list.remove(watcher);
    }

    @Override
    public void notifyWatchers(String str) {

        //遍歷,通知所有觀察者被觀察對象的消息變化
        for(Watcher watcher : list){
            watcher.update(str);
        }

    }
}
(5)測試類:

public class Test {
    public static void main(String[] args)throws Exception{

        //新建一個被觀察者對象:小明
        Watched xiaoming = new ConcreteWatched();

        //新建3個觀察者來監聽小明的狀態
        Watcher watcher1 = new ConcreteWatcher();
        Watcher watcher2 = new ConcreteWatcher();
        Watcher watcher3 = new ConcreteWatcher();

        //把監聽器安裝在小明身上
        xiaoming.addWatcher(watcher1);
        xiaoming.addWatcher(watcher2);
        xiaoming.addWatcher(watcher3);

        //小明的狀改變了
        xiaoming.notifyWatchers("我打算要偷東西了");
        
    }
}
輸出如下:

 我打算要偷東西了
 我打算要偷東西了
 我打算要偷東西了

第二個例子:利用Observable和Observer這兩個類來實現

import java.util.Observable;
import java.util.Observer;
需要配置builde.gradle(app)環境,添加如下兩行(這裏先把RxAndroid的一起添加了)

    compile 'io.reactivex:rxandroid:1.1.0' // RxAndroid
    compile 'io.reactivex:rxjava:1.1.0' // 推薦同時加載RxJava
(1)創建SimpleObservable類,繼承Observable類:

在裏面定義一個數據data,並創建getData()方法,和setData()方法,

再在setData()方法裏面設置狀態改變監聽與通知觀察者的方法,如下:

            //設置狀態改變
            setChanged();
            //表示狀態改變,通知觀察者
            notifyObservers();
整體代碼:

import java.util.Observable;

/**
 * Created by maiyu on 2017/6/18.
 * 創建一個被觀察者類
 */

public class SimpleObservable extends Observable {

    //定義一個數據
    private int data = 0;

    //get方法
    public int getData() {
        return data;
    }

    /**
     * setData方法
     * @param i
     */
    public void setData(int i) {
        if(this.data != i) {
            this.data = i;

            //設置狀態改變
            setChanged();
            //表示狀態改變,通知觀察者
            notifyObservers();
        }
    }
}
(2)創建觀察者類:SimpleObserver類,繼承Observer:

     初始化構造方法(把被觀察者作爲參數),重寫update方法

在update裏實現通知,代碼如下:

import java.util.Observer;

/**
 * Created by maiyu on 2017/6/18.
 * 觀察者
 */

public class SimpleObserver implements Observer {

    /**
     * 初始化,爲被觀察者添加觀察者對象
     * @param observable
     */
    public SimpleObserver(SimpleObservable observable){
        observable.addObserver(this);

    }

    /**
     * 當被觀察者的數據改變時,觸發此方法
     * @param o
     * @param object
     */
    @Override
    public void update(Observable o, Object object) {

        //強制轉換爲SimpleObservable類,並執行它的getData()方法
        System.out.println("data is changed: " + ((SimpleObservable)o).getData());

    }
(3)測試類:

public class Test {
    public static void main(String[] args)throws Exception{

        //創建被觀察者對象
        SimpleObservable observable = new SimpleObservable();
        //創建觀察者對象,把被觀察者當做參數
        SimpleObserver observer = new SimpleObserver(observable);

        observable.setData(1);
        observable.setData(2);
        //此處,因爲狀態還是2,沒有改變,不會通知
        observable.setData(2);
        observable.setData(3);

    }
}
輸出結果:

 data is changed: 1
 data is changed: 2
 data is changed: 3
只有在狀態改變時才通知,不改變不通知

三,RxAndroid:

在Android編程時,經常會使用後臺線程,那麼就可以使用這種方式,目前的異步編程方式會導致一些問題,如:

(1).異步任務容易導致內存泄漏

(2)CursorLoaders和ContentProvider的使用經常需要大量的配置數字模板

(3)後臺服務長時間運行在後臺,不能很快結束操作,會浪費資源

(4)訪問網絡接口調用返回數據,尤其在使用回調時候,處理數據很麻煩


1.創建觀察者

在異步模型中創建觀察者:

(1)定義一個方法,它完成某些任務,然後從異步調用中返回一個值,這個方法是觀察者的一部分

(2)將這個異步調用本身定義爲一個Observable

(3)觀察者通過訂閱(Subscribe)操作關聯到哪個Observable

(4)繼續你的業務邏輯,等方法返回時,Observable會發射結果,觀察者的方法會開始處理結果或者結果集

2.觀察者回調方法:onNext, onError , onComplete

(1)onNext(T item):Observable調用這個方法發射數據,方法的參數就是Observable發射的數據,這個方法可能會被多次調用,取決於我們的實現

(2)onError(Exception ex)

當Observable遇到錯誤或者無法返回期望的數據時會調用這個方法,這個調用會終止Observable,後續不會再調用onNext和onCompleted,

onError方法的參數就是拋出的異常

(3)onComplete

正常終止,如果沒有遇到錯誤,Observable在最後一次調用onNext之後調用此方法

3.創建操作Create:

(1)使用一個函數從頭開始參加一個Observable:

Create{onNext    ;  onNext   ; onComplete}

注意:可在傳遞給create方法的函數中檢查觀察者的isUnsubscribed狀態,以便在沒有觀察者的時候,讓你的Observable停止發射數據或做昂貴的運算。

4.例子如下:

創建類:RxUtils,用於存放後面沒種實現方式的方法

public class RxUtils {

    private static final String TAG = RxUtils.class.getSimpleName();
<1>第一例子:使用Observable.create()方法來創建:

(1)創建Observable對象,在create方法裏面傳入參數new Observable.OnSubscribe()對象,

然後利用onNext設置信息,最後調用onComplete()方法,如下:

        //使用Observable.create方法來創建
        Observable<String > observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {

                subscriber.onNext("hello");
                subscriber.onNext("good");
                subscriber.onNext(downLoadJson());
                subscriber.onNext("約嗎");

                //調用onCompleted()方法來完成
                subscriber.onCompleted();
            }
        });
(2)創建Subscriber對象,重寫onError,onComplete,onNext方法:

代碼如下:

        //創建Subscriber對象,這裏傳入字符串類型,因爲什麼我們是發送字符串
        Subscriber<String> showsub = new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.i(TAG , "onCompleted");
            }

            @Override
            public void onError(Throwable e) {

                Log.i(TAG , "onError:"+ e.toString());
            }

            @Override
            public void onNext(String s) {

                Log.i(TAG , "onNext: " + s);
            }
        };
    /**
     * 定義下載方法
     * @return
     */
    private static String downLoadJson() {
        return "json_data";
    }

(3)調用Observable對象的subscribe關聯Subscriber對象:

        /**
         * 關聯被觀察者
         */
        observable.subscribe(showsub);
(4)在Activity中爲某個按鈕設置監聽:

    public void btnOnClick(View view){
        RxUtils.createObservable();
    }
(5)輸出結果如下:

06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: hello
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: good
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: json_data
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: 約嗎
06-20 01:30:46.313 6162-6162/? I/RxUtils: onCompleted

<2>第二種方法:也是利用create方法,只是不用創建Observable和Subscriber對象,而是直接實現,如下:打印整數1到10

    public static void createObservable2(){

        Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                //如果沒有解除關聯
                if(!subscriber.isUnsubscribed()){

                    for(int i = 0 ; i < 10 ; i++){
                        subscriber.onNext(i);
                    }
                    subscriber.onCompleted();
                }

            }
        }).subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.i(TAG , "onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                Log.i(TAG , "e: " + e.toString());
            }

            @Override
            public void onNext(Integer integer) {
                Log.i(TAG , "onNext: " +integer);
            }
        });

    }
Activity中按鈕監聽:

    public void btnOnClick2(View view){
        RxUtils.createObservable2();
    }
輸出結果:

06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 0
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 1
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 2
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 3
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 4
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 5
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 6
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 7
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 8
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 9
06-20 01:36:37.593 6162-6162/? I/RxUtils: onCompleted

<3>第3種方法:from()方法,定義數組

    /**
     * Observable.from()方法
     * 使用在被觀察者,返回的一般都是數據類型
     */
    public static void from(){

        Integer[] items = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9};
        Observable observable = Observable.from(items);

        observable.subscribe(new Action1() {
            @Override
            public void call(Object o) {

                Log.i(TAG , o.toString());
            }
        });

    }
輸出:

06-20 02:01:43.081 6162-6162/? I/RxUtils: 1
06-20 02:01:43.081 6162-6162/? I/RxUtils: 2
06-20 02:01:43.081 6162-6162/? I/RxUtils: 3
06-20 02:01:43.081 6162-6162/? I/RxUtils: 4
06-20 02:01:43.081 6162-6162/? I/RxUtils: 5
06-20 02:01:43.081 6162-6162/? I/RxUtils: 6
06-20 02:01:43.081 6162-6162/? I/RxUtils: 7
06-20 02:01:43.081 6162-6162/? I/RxUtils: 8
06-20 02:01:43.081 6162-6162/? I/RxUtils: 9
                                          
                                          --------- beginning of /dev/log/system

<4>第4種:Interval指定時間間隔發送數據:

    /**
     * interval指定某一時刻進行數據發送:定時器
     */
    public static void interval(){

        //每隔1秒發送一次數據
        Observable observable = Observable.interval(1 , 1 , TimeUnit.SECONDS);
        observable.subscribe(new Action1() {
            @Override
            public void call(Object o) {
                Log.i(TAG , o.toString());
            }
        });

    }

輸出結果:發現每隔1秒,後臺就打印一個數據,,截取部分如下:

06-20 02:04:28.997 25326-25438/? I/RxUtils: 0
06-20 02:04:29.997 25326-25438/? I/RxUtils: 1
06-20 02:04:30.997 25326-25438/? I/RxUtils: 2
06-20 02:04:32.001 25326-25438/? I/RxUtils: 3
06-20 02:04:32.997 25326-25438/? I/RxUtils: 4
...

<5>第5種:just來實現範圍數據,參數爲多個數組對象,如:

    /**
     * 範圍數據:如下面依次輸出兩個數組的元素
     */
    public static void just(){

        //定義兩個數組
        Integer[] items1 = {1 , 3 , 5 , 7 , 9};
        Integer[] items2 = {2 , 4 , 6 , 8 , 10};

        //調用Observable.just(數組1,數組2,.....數組10);
        Observable observable   =   Observable.just(items1 , items2);

        //在這裏設置Subscriber的類型爲Integer[]:對應上面的Integer類型的數組
        observable.subscribe(new Subscriber<Integer[]>() {
            @Override
            public void onCompleted() {
                Log.i(TAG , "onCompleted");
            }

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

            @Override
            public void onNext(Integer[] o) {
                for(Integer i : o)
                    Log.d(TAG , "onNext : " +i);
            }
        });

    }
輸出結果:依次輸出兩個數組的數據

06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 1
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 3
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 5
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 7
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 9
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 2
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 4
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 6
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 8
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 10
06-20 02:07:00.337 25643-25643/? I/RxUtils: onCompleted
<6>第6種:利用range來實現從指定初始位置和個數的範圍,如:

    /**
     * range方法:定義開始下標與個數
     */
    public static void range(){

        //利用Observable.range(開始下標,個數);
        Observable observable   =   Observable.range(3 , 5);

        //傳入Action1的參數類型Integer
        observable.subscribe(new Action1<Integer>() {

            @Override
            public void call(Integer integer) {
                Log.d(TAG , "call : " + integer);
            }
        });
    }
輸出結果:

06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 3
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 4
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 5
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 6
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 7
                                            
                                            --------- beginning of /dev/log/system
<7>第7種:利用filter來實現某些過濾信息:

    /**
     * Observable.filter()方法:用於過濾某些東東
     */
    public static void filter(){

        //創建一個數組
        Integer[] items = {1 , 2 , 3 , 4 , 5 , 6};
        //調用from添加
        Observable observable = Observable.from(items);
        //添加過濾器,傳入<Integer,Boolean>參數:過濾小於等於3的數字
        observable.filter(new Func1<Integer , Boolean>() {

            @Override
            public Boolean call(Integer integer) {
                return integer > 3;
            }
        })
                //設置訂閱者是如何執行的:Schedulers.io---通過網絡獲取數據
                .observeOn(Schedulers.io())
                .subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.d(TAG , "onCompleted");
            }

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

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG , "onNext : " + integer);
            }

        });
    }
結果如下:

06-20 02:13:52.561 26628-26661/? D/RxUtils: onNext : 4
06-20 02:13:52.561 26628-26661/? D/RxUtils: onNext : 5
06-20 02:13:52.561 26628-26661/? D/RxUtils: onNext : 6
06-20 02:13:52.561 26628-26661/? D/RxUtils: onCompleted


四,RxAndroid應用場景

1.替代AsyncTask完成下載操作

2.結合OkHttp完成網絡訪問操作、包括下載文件、提交form表單數據

3.結合ListView、GridView使用完成對圖文混排操作

4.結合OkHttp網絡訪問框架使用

5.RxAndroid編程思路的總結


1.替代AsyncTask完成下載操作:如下載一直圖片

(1)在Activity中:

 * 在實際開發中Activity充當的角色太多了:
 * 1.UI主線程負責繪製UI
 * 2.開啓子線程獲取網絡數據
 * 3.賦值到控件中
 * 4.判斷邏輯等等

而下載圖片常用方法:

/**
 * 下載張圖片:
 * 1.AsyncTask
 * 2.Handler機制
 * 3.發現有更好的即觀察者模式
 */
如第1種:那麼必須創建類繼承AsyncTask<String , 參數,byte[]>等

或者自己封裝:

public class DownLoadUtils {

    /**
     * 傳統模式,
     *
     * @param path
     * @return
     */
    public static byte[] downloadImg(String path, CallBack callBack) {
        //在這裏定義異步任務

        return null;

    }

    interface CallBack {
        void callback(byte[] data);
    }

}

但是發現這些太繁瑣或是消耗資源多,於是採用第3種:

(2)創建工具類:

主要有如下幾個知識點:

------定義並在構造方法裏創建OkHttpClient

記得在build.gradle添加OkhttpClient的依賴

    compile 'com.squareup.okhttp:okhttp:2.7.2'
------使用Observable創建下載方法,參數爲path,

public class DownLoadUtils {

    //定義OkHttpClient
    private OkHttpClient okHttpClient ;

    /**
     * 構造函數:實例化OkHttpClient對象
     */
    public DownLoadUtils(){
        okHttpClient = new OkHttpClient();
    }


    /**
     * 創建觀察者模式的下載方法,這裏
     * @param path      -----傳入地址參數
     * @return          ------返回btye[]數組
     */
    public Observable<byte[]> downloadImg(final String path){

        //使用create()方法
        return Observable.create(new Observable.OnSubscribe<byte[]>() {
            @Override
            public void call(final Subscriber<? super byte[]> subscriber) {

                //判斷是否已經綁定訂閱
                if(!subscriber.isUnsubscribed()){

                    //使用OkhttpClient訪問網絡步驟
                    //創建Request對象,調用.url()傳入地址,build()完成
                    Request request = new Request.Builder().url(path).build();
                    //調用okttpClient.newCall(Request對象).enqueue()執行異步get請求
                    okHttpClient.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Request request, IOException e) {
                            //執行subscriber.onError()方法
                            subscriber.onError(e);
                        }

                        /**
                         * 請求成功
                         * @param response
                         * @throws IOException
                         */
                        @Override
                        public void onResponse(Response response) throws IOException {

                            //判斷返回結果是否成功
                            if(response.isSuccessful()){
                                //獲取返回的byte[]數組
                                byte[] data = response.body().bytes();
                                //判空
                                if(data != null){
                                    //發射數據
                                    subscriber.onNext(data);
                                }
                            }
                            //完成
                            subscriber.onCompleted();
                        }
                    });
                }
            }
        });

    }


}
在Activity中:

初始化DownLoad類:

utils = new DownLoadUtils();
爲按鈕設置監聽,在監聽裏面執行代碼如下:

                //下載圖片------設置訂閱執行方式(通過網絡獲取數據)-----設置主線程顯示
                utils.downloadImg(imgPath).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Subscriber<byte[]>() {
                            @Override
                            public void onCompleted() {
                                Log.i(TAG , "onCompleted");//對話框取消
                            }

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

                            @Override
                            public void onNext(byte[] bytes) {

                                //顯示圖片,這裏沒有對圖片進行壓縮等處理
                                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes , 0 , bytes.length);
                                mImg.setImageBitmap(bitmap);
                            }
                        });

結果:顯示一張圖片:

如傳入地址:

 private String imgPath = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497953788142&di=370d893f7390ea12dc770083b171c1f2&imgtype=0&src=http%3A%2F%2Fxke8.com%2Fuploads%2Fallimg%2Fc150921%2F1442O51G4A0-1I13.jpg";
有點長,不過結果辣眼睛,瞬間秒殺你的睏意:





2.利用OkhtttpClient實現用戶登錄:

主要代碼如下:

工具類:

/**
 * Created by maiyu on 2017/6/20.
 * 登錄類
 */

public class LoginUtils {
    //定義OkHttpClent對象
    private OkHttpClient okHttpClient ;
    public LoginUtils(){
        okHttpClient = new OkHttpClient();
    }

    /**
     * 登錄實現
     * @param url
     * @param params
     * @return  String
     */
    public Observable<String> login(final String url , final Map<String , String> params){

        return  Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(final Subscriber<? super String> subscriber) {

                //判斷是否已經綁定
                if(!subscriber.isUnsubscribed()){

                    //創建FormEncodingBuilder對象
                    FormEncodingBuilder builder = new FormEncodingBuilder();

                    //添加參數
                    if(params != null && !params.isEmpty()){
                        for(Map.Entry<String , String> entry : params.entrySet()){

                            builder.add(entry.getKey() , entry.getValue());
                        }
                    }
                    //創建RequestBody對象
                    RequestBody body = builder.build();

                    //創建Request對象
                     Request request = new Request.Builder().url(url).post(body).build();

                    okHttpClient.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Request request, IOException e) {
                            subscriber.onError(e);
                        }

                        @Override
                        public void onResponse(Response response) throws IOException {

                            if(response.isSuccessful()){
                                //訂閱
                                subscriber.onNext(response.body().string());
                            }
                            subscriber.onCompleted();
                        }
                    });
                }



            }
        });


    }
}
登錄按鈕監聽實現:

    public void toLogin(){


        Map<String , String> params = new HashMap<String , String>();
        params.put("username" , "獲取用戶名");
        params.put("password" , "獲取密碼");

        loginUtils.login(loginUrl , params).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        Log.i(TAG , "onCompleted");
                    }

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

                    @Override
                    public void onNext(String s) {

                        //跳轉...
                        Intent intent = new Intent();
                        startActivity(intent);
                    }
                });
        
    }


附註代碼下載地址:代碼下載地址





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