天天看點

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";
           

有點長,不過結果辣眼睛,瞬間秒殺你的困意:

RxAndroid學習筆記&lt;一&gt;

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);
                    }
                });
        
    }
           

附注代碼下載下傳位址: 代碼下載下傳位址