android 積累一些關於rxjava的知識點


rxjava在我看來就是一套比較先進的asynctask,用來處理異步請求的一種規範(得益於它的代碼思路清晰),在android中可以用來代替asynctask甚至是handler。常與當前流行網絡請求框架retrofit2一同使用。


rxjava的採用了觀察者模式:Observer/Subscriber(觀察者),Observable(主題)。個人喜歡把Observer/Subscriber當做事件的消費者,Observable當做是事件的產生者。


優點:線程切換(android 網絡請求與UI刷新),邏輯清晰



android-studio 環境配置:


   compile 'io.reactivex:rxjava:1.0.14'
   compile 'io.reactivex:rxandroid:1.0.1'

Observer/Subscriber(觀察者)

 Observer<String>  observer=new Observer<String>() {
            @Override
            public void onCompleted() {
                Log.i("rxjava::","onCompleted::");

            }

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

            }

            @Override
            public void onNext(String s) {

                /**
                 * 被觀察者“發給” 觀察者的消息
                 * 可以理解成 事件在這裏消費
                 */

                Log.i("rxjava::","onNext::"+s);

            }
        };

 Subscriber<String>  subscriber=new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.i("rxjava::","onCompleted::");

            }

            @Override
            public void onStart() {
                super.onStart();
                Log.i("rxjava::","onStart::");

            }

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

            }

            @Override
            public void onNext(String s) {
                Log.i("rxjava::","onNext::"+s);

            }
        };

觀察者兩種寫法的區別:

1.Subscriber 對 Observer 接口進行了一些擴展,即Subscriber 裏可以重寫一個onstart的方法

2.onstart方法:在被觀察者“發送”消息之前。我也不知道有什麼軟用,不能加載進度條(因爲不在UI線程)


Observable(被觀察者)

 Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                //事件中心
                subscriber.onNext("hasaki");

                subscriber.onNext("mianduijifengba");


                subscriber.onCompleted();//此句話要是不調用   觀察者裏的oncompleted方法就不會調用

            }
        });


Subject:也是一種事件的產生與發送者,可替代Observable

PublishSubject.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("nihao");
            }
        }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {

                Log.i("TTTTT:::",s+"???");
            }
        });












當然被觀察者還可以使用固定的方法來“發送數據給觀察者”

just(傳入要發送的數據序列並用逗號隔開);
/**
* 此方法默認在執行結束加上onCompleted();
*/
 Observable<String> observable =  Observable.just("hasaki","mianduijifengba");

from(可傳入對象數組);

        String[]  requestArray={"hasaki","mianduijifengba"};
        /**
         * 此方法默認在執行結束加上onCompleted();
         */
        Observable<String> observable = Observable.from(requestArray);

訂閱:“被觀察者去訂閱觀察者”:原因是:流式API設計(什麼鬼?)

 //訂閱
 observable.subscribe(subscriber);

取消訂閱:(對於異步請求結束後,要解除引用關係,避免內存泄漏)
一般訂閱之後都會產生一個Subscription對象


        //訂閱
        Subscription subscribe = observable.subscribe(subscriber);

        if(subscribe.isUnsubscribed()){
            //判斷是否解除訂閱
            Log.i("rxjava","沒有解除訂閱");

            subscribe.unsubscribe();//解除訂閱


        }else{
            Log.i("rxjava","解除訂閱");
        }

初級進階(線程控制)

因爲被觀察者是"事件的產生者",而觀察者是"事件的消費者",通常在網絡請求中,被觀察者裏開啓子線程做網絡請求,觀察者裏要在UI線程中跟新UI,主要運用到兩個方法:

 observable.subscribeOn();//設置被觀察者裏事件產生所處的線程,即:調用call方法所處的線程
        
 observable.observeOn();//觀察者,事件消費所處的線程即:onNext

線程分類:
Schedulers.immediate()//當前線程,即默認
Schedulers.newThread()//顧名思義,開啓新線程
Schedulers.io()//相當於cacheThreadPool  維護一個不定數量的線程池,還可重複利用
AndroidSchedulers.mainThread()//android 專利,顧名思義,即主線程。
example:開啓線程讀取數據,UI線程跟新數據::
       String[] requestArray = {"hasaki", "面對疾風吧"};

        Observable.from(requestArray)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {

                        tv.setText(s);

                    }
                });

中級進階(變換)
所謂變換,就是將事件序列中的對象或整個序列進行加工處理,轉換成不同的事件或事件序列。

1.Map(轉換類操作符)單個轉換

什麼是轉成不同的事件?
說白了就是我要把現金存入支付寶,我的事件隊列是現金,我最後想要的事件結果是支付寶裏有錢,可是現金不能直接存支付寶,得先變換一下
,即先存銀行卡轉成電子貨幣,最後支付寶轉賬。(轉單個事件)
/**
         * 假設字符串格式爲現金
         * int格式爲電子貨幣
         * func:字符串轉int
         */
        Observable.just("100").map(new Func1<String, Integer>() {
            @Override
            public Integer call(String s) {
                //先轉電子貨幣
                return Integer.valueOf(s);
            }
        }).subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Integer integer) {

                Log.i("電子貨幣轉支付寶::", integer + "");

            }
        });

map的功能:即對象的一對一轉換,當被觀察者事件產生了,先執行map裏的方法,再到觀察者消費事件(對象的直接變換)

func1:提供了一個有形參和返回值的call方法(call方法?秀等麻袋,請自行對比一下之前被觀察者裏產生事件的call方法,先埋一個坑)

2.flatMap(轉換類操作符)

那轉不同的事件序列呢?(也就是轉一堆)
example:假設一天馬雲爸爸閒的蛋疼,他想看看他的支付寶後臺,他想知道每個人的名字,以及每個人都綁定了什麼樣的銀行卡。就是循環打印人名和循環
打印card名,假設類該這麼寫:Person類裏維護了一個name和card數組,card類裏維護了cardname和cardmoney
 Person[] persons = {new Person("張三", new Card[]{new Card("工商", "100"), new Card("農行", "200")}),
                new Person("亞索", new Card[]{new Card("工商", "300"), new Card("農行", "400")})
        };

        Observable.from(persons).flatMap(new Func1<Person, Observable<Card>>() {
            @Override
            public Observable<Card> call(Person person) {

                Log.i("rxjava::", person.getName());

                return Observable.from(person.getCards());
            }
        }).subscribe(new Subscriber<Card>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Card card) {

                Log.i("rxjava::", card.toString());

            }
        });
flatMap:對象轉新的事件序列,注意func1返回值的變換,他返回的是一個被觀察者對象,然後又拿着這個對象去
請求新的序列。
這裏的應用環境究竟是什麼樣的呢,假設你要讀取列表中的某個key,然後拿着這key讀取新的列表
會用到吧?我也沒用過啊,我是邊看別人的博客,寫下自己的理解。
我的理解:將一堆事件序列轉成一個Observerble再統一發出去
flatMap的交叉問題:假設現有一個數組person[3]{校長,老師,學生},經過flatMap要求得到每個人身上的錢,
也許取的第一個對象是校長,第二個是老師,也許取的第一個對象是校長,第二個對象是學生。也就是說只
保證鋪平序列,不能保證發送序列的順序。
問題:我寫的例子裏,都是正常發送的順序未發現錯亂,也許是數據源基數太小。

3.contatMap(轉換類操作符)

作用類似於flatMap但不會產生交叉問題,也就是正常按發送順序發送

User[]  users=new User[]{new User("張三","22"),new User("李四","23"),new User("老王","24")};

        Observable.from(users).concatMap(new Func1<User, Observable<String>>() {
            @Override
            public Observable<String> call(User user) {
                return Observable.just(user.getFirstName());
            }
        }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.i("YYYYTTT::",s);
            }
        });

4.scan(轉換類操作符)

Observable.just(1, 2, 3, 4, 5)
                .scan(new Func2<Integer, Integer, Integer>() {
                    @Override
                    public Integer call(Integer integer, Integer integer2) {
                        Log.i("YYYYTTT????", integer+"/"+integer2);
                        return integer + integer2;
                    }
                }).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.i("YYYYTTT::", integer+"");
            }
        });

打印結果::

先直接返回第一個結果,然後此結果作爲下一個結果的第一個條件參數。
對一個序列的數據應用一個函數,並將這個函數的結果發射出去作爲下個數據應用合格函數時的第一個參數使用。

5.filter(過濾操作符)

 List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).filter(new Func1<User, Boolean>() {
            @Override
            public Boolean call(User user) {
                if (user.getFirstName().equals("張三")){
                    return false;//過濾掉
                }else{
                    return true;//留着
                }
            }
        }).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });



6.take(過濾操作符)

//找出數據序列前三個數據
        List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).take(3).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });


//找出第一項數據 first == take(1)
        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable.from(users).first().subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });







//找出數據序列中最後三條數據
        List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).takeLast(3).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });



//一直讀,知道滿足條件爲止,包含滿足條件的那條


        List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).takeUntil(new Func1<User, Boolean>() {
            @Override
            public Boolean call(User user) {
                if (user.getFirstName().equals("大錘")){
                    return true;//讀到此處不再讀取
                }else{
                    return  false;
                }

            }
        }).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });


7.skip(過濾操作符)

忽略掉數據序列中的前多少項

        List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).skip(3).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });

//忽略後三項的數據
        List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).skipLast(3).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });



8.elementAt(過濾操作符)

只獲取數據序列中的某一項數據

//獲取第四項數據
        List<User>  users=new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "22"));
        users.add(new User("大錘", "25"));

        Observable.from(users).elementAt(3).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });




9.distinct(過濾操作符)

過濾掉重複的元素
        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable.from(users).distinct().subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::", user.toString());
            }
        });



//可還是有兩條數據相等,足以可見其判斷相同的機制不滿足於對象與對象之間的比較
//所有還可以更加細節的過濾
        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));
        
        Observable.from(users).distinct(new Func1<User, String>() {
            @Override
            public String call(User user) {
                return user.getFirstName();//過濾掉重名
            }
        }).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });



10.last last == takeLast(1)

最後一項

        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable.from(users).last().subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("GGGDDD::",user.toString());
            }
        });

11.merge(組合操作符)

將多個發射序列合併成一個發射序列,新序列裏的數據是無序的

        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable<User> ob1 = Observable.from(users);

        Observable<Integer> ob2 = Observable.just(1, 2, 3, 4);


        Observable.merge(ob1, ob2).subscribe(new Subscriber<Object>() {
            @Override
            public void onCompleted() {
                
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Object o) {
                
                Log.i("TTGGG:::",o.toString());

            }
        });


???說好無序的呢?難道測試數據過小?
12.startWith(組合操作符)
發射數據之前插入一條相同類型的新數據或者相同類型的新發射序列
        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable.from(users).startWith(new User("帥哥","18")).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                Log.i("TTTDDDD::",user.toString());
            }
        });



13.concat(組合操作符)
多個發射序列,逐個序列數據發出,接收的數據一定是順序的
        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable<User> ob1 = Observable.from(users);


        Observable<Integer> ob2 = Observable.just(1, 2, 3, 4, 5);


        Observable.concat(ob1, ob2).subscribe(new Action1<Object>() {
            @Override
            public void call(Object o) {
                Log.i("TTGGGD:",o.toString());
            }
        });


14.zip(組合操作符)
1+1組合,

        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable<User> ob1 = Observable.from(users);


        Observable<Integer> ob2 = Observable.just(1, 2, 3, 4, 5,6);


       Observable.zip(ob1, ob2, new Func2<User, Integer, String>() {
           @Override
           public String call(User user, Integer integer) {
               return user.getFirstName()+integer;
           }
       }).subscribe(new Action1<String>() {
           @Override
           public void call(String s) {
               Log.i("TGGDD::",s);
           }
       });


15.combineLatest(組合操作符)

第一個發射序列的最後一個元素與第二個發射序列的所有元素組合
        List<User> users = new ArrayList<User>();
        users.add(new User("張三", "22"));
        users.add(new User("李四", "24"));
        users.add(new User("老王", "25"));
        users.add(new User("大錘", "25"));
        users.add(new User("大錘", "25"));

        Observable<User> ob1 = Observable.from(users);


        Observable<Integer> ob2 = Observable.just(1, 2, 3, 4, 5,6);


       Observable.combineLatest(ob1, ob2, new Func2<User, Integer, String>() {
           @Override
           public String call(User user, Integer integer) {
               return user.getFirstName()+integer;
           }
       }).subscribe(new Action1<String>() {
           @Override
           public void call(String s) {
               Log.i("TGGDD::",s);
           }
       });








總結:既然rxjava裏可以轉換,那麼轉換處在哪個線程裏呢,轉換通通處在觀察者的線程裏
即你在轉換之前observable.observeOn()設定的是什麼線程,它就處在什麼線程裏。
高級進階:
rxjava+retrofit2
關於retrofit2我也在學習中,先做簡單的使用:
導入:
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'

別忘了添加網絡權限,切記要添加
addCallAdapterFactory(RxJavaCallAdapterFactory.create())//讓rxjava能使用retrofit2

 private void initData() {
        Retrofit retrofit = new Retrofit.Builder().baseUrl("http://fdj.abc5.cn")
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        HttpUser httpUser = retrofit.create(HttpUser.class);

        httpUser.getUsers("hcy", "1234")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        Log.i("網絡請求的數據::", "onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("網絡請求的數據::", "onError" + e.getMessage());
                    }

                    @Override
                    public void onNext(String s) {

                        Log.i("網絡請求的數據::", s);
                        tv.setText(s);

                    }
                });
        
    }


    public interface HttpUser {
        @POST("/api/index/posttest")
        @FormUrlEncoded
        Observable<String> getUsers(@Field("username") String username, @Field("password") String password);
    }

小結:
關於Action1,Action0,Func1使用與區別:
Func1:有形參,有返回
Func2:多個形參,有返回
Action1:有形參,無返回
Action0:無形參,無返回
Action1,Action0可以代替觀察者裏的三個方法,OnNext,OnError,OnCompleted;
Action1<String> onNextAction = new Action1<String>() {
            // onNext()
            @Override
            public void call(String s) {
                Log.i("onNext:::",s);
            }
        };
        Action1<Throwable> onErrorAction = new Action1<Throwable>() {
            // onError()
            @Override
            public void call(Throwable throwable) {
                Log.i("onError:::",throwable.getMessage());
            }
        };
        Action0 onCompletedAction = new Action0() {
            // onCompleted()
            @Override
            public void call() {
                Log.i("onCompleted","");
            }
        };
        Observable.just("hasaki","posigei").subscribe(onNextAction,onErrorAction,onCompletedAction);
如何多次切換線程::
(線程切換容易出現的異常::java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
找到異常的最後一般又可以看到::Caused by: android.os.NetworkOnMainThreadException)
example:像我所在的公司要強求服務器的一條連接,要請求兩次,第一次請求服務器的時間,然後按
字母順序將請求的參數排序在最後加載請求的時間和appkey字段形成sign,再把sign和時間放入
參數map中請求第二個連接才能得到想要的數據,是不是賊幾把麻煩,以前封裝的時候因爲要考慮到
其實是兩次網絡請求(不能放在主線程中,android基礎),但請求得到的數據我又想能切換到主線程
跟新UI,以前的代碼一大堆,現在貼出我第一次封裝的代碼,感受下rxjava切換線程的好處
package utils;

import android.util.Log;

import com.alibaba.fastjson.JSON;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import contact.Contact;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PartMap;
import retrofit2.http.Url;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * Created by hcy on 2016/12/24.
 */

public class WytHttpUtils {

    public interface HttpServerTime {
        @GET("/api/getservicetime.php")
        Observable<HttpTime> HttpTime();
    }


    public interface HttpResult {
        @POST
        @Multipart
        Observable<String> httpResult(@Url String url, @PartMap Map<String, RequestBody> params);
    }


    private Map<String, String> map;


    public WytHttpUtils(Map<String, String> map) {
        this.map = map;
    }


    public void HttpRequest(String url) {
        ServiceFactory.createServiceFrom(HttpServerTime.class, "http://iexue.quxue100.cn")
                .HttpTime()
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .flatMap(new Func1<HttpTime, Observable<String>>() {
                    @Override
                    public Observable<String> call(HttpTime httpTime) {

                        Log.i("DDDSSS222::", httpTime.toString());
                        if (httpTime.getStatus() == 1) {
                            //時間獲取成功
                            String sign = getValueFromMap(map).append(httpTime.getResult()).append(Contact.APPKEY).toString();
                            map.put("time", httpTime.getResult() + "");
                            map.put("sign", md5Encode(sign));
                            getValueFromMap2(map);
                            Observable<String> observable1 =  ServiceFactory.createServiceFrom(HttpResult.class,"http://iexue.quxue100.cn").httpResult(url, getValueFromMap2(map));
                            return observable1;
                        } else {
                            return null;
                        }

                    }
                }).observeOn(AndroidSchedulers.mainThread())//切換到主線程
                .subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.i("rxjava::onCompleted:", "onCompleted");

            }

            @Override
            public void onError(Throwable e) {

                Log.i("rxjava::onError:", e.getMessage());

            }

            @Override
            public void onNext(String s) {

                Log.i("rxjava::onNext:", s);

            }
        });


        //return  observable;
    }


    private String md5Encode(String content) {
        //選擇摘要算法
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("md5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        //設置要摘要的內容:
        md.update(content.getBytes());
        //生成摘要
        byte[] value = md.digest();
        //轉16進制
        String md5Value = toHexString(value);
        return md5Value;
    }


    private String toHexString(byte[] value) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < value.length; i++) {
            //消除負數 我們認爲每一個byte都是正數
            int values = value[i] & 255;
            if (values < 16) {
                //如果值小於16 那麼使用Integer.toHexString算出來的值是0-f
                //必須補0
                sb.append("0");
            }
            sb.append(Integer.toHexString(values));
        }
        return sb.toString();
    }


    private StringBuffer getValueFromMap(Map<String, String> map) {

        Iterator iter = map.entrySet().iterator();
        StringBuffer buffer = new StringBuffer();

        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();

            Object val = entry.getValue();

            buffer.append(val + "");


        }
        return buffer;
    }


    private Map<String, RequestBody> getValueFromMap2(Map<String, String> map) {

        Iterator iter = map.entrySet().iterator();
        Map<String, RequestBody> requestBodyMap = new HashMap<String, RequestBody>();
        Log.i("DSDSDS::", map.size() + "");
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();

            String val = (String) entry.getValue();

            String key = (String) entry.getKey();

            Log.i("rxjava::", key + "???" + val);

            requestBodyMap.put(key, RequestBody.create(null, val));
            //photos.put("password",  RequestBody.create(null, "123456"));


        }
        return requestBodyMap;
    }

    private class HttpTime {


        public HttpTime(int status, String msg, int result) {
            this.status = status;
            this.msg = msg;
            this.result = result;
        }

        public HttpTime() {
        }


        @Override
        public String toString() {
            return "HttpTime{" +
                    "status=" + status +
                    ", msg='" + msg + '\'' +
                    ", result=" + result +
                    '}';
        }

        /**
         * status : 1
         * msg : 獲取成功
         * result : 1482549878
         */

        private int status;
        private String msg;
        private int result;

        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public int getResult() {
            return result;
        }

        public void setResult(int result) {
            this.result = result;
        }
    }

}


附錄:
rxjava 正計時 與 倒計時
package utils;
import android.content.Context;

import com.orhanobut.logger.Logger;

import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import lessonmodule.LessonActivity;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import wytnewhttp.WytHttpUtils;


/**
 * Created by hcy on 2017/2/24.
 */

public class RxUtils {
    //倒計時
    public static Observable<String> countDownTime(int time) {
        if (time < 0) {
            time = 0;
        }
        final int countTime = time;
        return Observable.interval(0,1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Func1<Long, String>() {
                    @Override
                    public String call(Long aLong) {
                        //解決八小時的時區問題
                        String format = new SimpleDateFormat("HH:mm:ss").format((countTime - aLong.intValue()) * 1000- TimeZone.getDefault().getRawOffset());

                        Logger.i("倒計時::"+format);
                        return format;
                    }
                })
                .take(countTime + 1);

    }


    //正計時

    public static Observable<String> countUpTime() {
        final int countTime = 0;
        return Observable.interval(0,1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Func1<Long, String>() {
                    @Override
                    public String call(Long aLong) {
                        return new SimpleDateFormat("HH:mm:ss").format((countTime + aLong.intValue())*1000);
                    }
                });
    }


    public static void unsubscribe(Subscription subscription) {
        if (subscription != null && !subscription.isUnsubscribed()) {
            subscription.unsubscribe();
        }
    }


}




      countTimeSubscription = RxUtils.countDownTime(60).subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        tv_countTime.setText(s);
                    }
                });


















發佈了43 篇原創文章 · 獲贊 30 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章