RxJava+Retrofit+MVP學(xué)習(xí)筆記

學(xué)習(xí)鏈接,都是跟著大佬一步步來的,本篇主要是自己的筆記
RxJava和Retrofit最近超火,不學(xué)不是人。

首先關(guān)于RxJava

概念

官方定義是羅里吧嗦一大堆看不懂,主要看這兩個詞就夠了,異步,基于事件。

  • 觀察者設(shè)計模式
    RxJava是基于觀察者和被觀察者模式,觀察者和被觀察者之間存在一種訂閱的關(guān)系,觀察者可以知道被觀察者某種事件下所發(fā)生的一切。


    觀察者模式
  • 基于事件
    你老婆拿著你的工資卡去商場購物,買了一個兩萬塊錢的包包,這時候你就可以收到銀行發(fā)來的一條消費兩萬元的短信,這個時候你就是觀察者,你老婆就是被觀察者。
    但你不可能觀察你老婆所有的事情吧,比如問了個路、喝了杯咖啡等等,這些你老婆不告訴你你是不會知道的,你能知道的僅僅是你老婆花了兩萬塊錢買了個很貴的包而已。
    凡是你卡里余額變動,你都能知道,我們可以說這是基于銀行卡余額變動事件下的觀察者模式??偨Y(jié)四個字:基于事件。

  • 異步
    RxJava它是異步的。這個比較好理解,就好像我去蛋糕店買蛋糕,我跟老板說了我想要什么樣的蛋糕,然后我告訴老板我什么時候來取,不必一直在蛋糕店里等著,我可以去忙其它的事,這就是異步。

  • 操作符轉(zhuǎn)變
    被觀察者是可以通過某種操作符轉(zhuǎn)變的,就是用一個操作符可以把被觀察者改變的意思.....
    RxJava中也內(nèi)置了許多操作符,可以把被觀察者進(jìn)行轉(zhuǎn)變,轉(zhuǎn)變?yōu)榱硗庖环N形態(tài)以后在研究..

創(chuàng)建一個觀察者模式

1.創(chuàng)建被觀察者。
ObservableEmitter有三種的方法,

  • void onNext(T value),方法可以無限調(diào)用
  • void onError(Throwable error),不可以重復(fù)調(diào)用
  • void onComplete(),OnComplete可以重復(fù)調(diào)用,但是Observer(觀察者)只會接收一次
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                 //把這個消息發(fā)送出去。
                emitter.onNext("我花了兩萬塊錢買了個包");
            }
        });

2.創(chuàng)建觀察者。

Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String msg) {
                //你收到買包的消息。
                Log.e("RxJava--------------",msg);
                //你暗罵的話。
                Log.e("RxJava--------------","收到了,敗家娘們");

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };

3.訂閱

//訂閱。
observable.subscribe(observer);

RxJava2.0的異步和鏈?zhǔn)骄幊?/h2>

前言里面有提到,RxJava是支持異步的
需要Scheduler。Scheduler,英文名調(diào)度器,它是RxJava用來控制線程。
當(dāng)我們沒有設(shè)置的時候,RxJava遵循哪個線程產(chǎn)生就在哪個線程消費的原則,也就是說線程不會產(chǎn)生變化,始終在同一個。
RxJava后臺執(zhí)行,前臺調(diào)用,這個原則,我們需要調(diào)用observeOn(AndroidSchedulers.mainThread()),observeOn是事件回調(diào)的線程,AndroidSchedulers.mainThread()一看就知道是主線程,subscribeOn(Schedulers.io()),subscribeOn是事件執(zhí)行的線程,Schedulers.io()是子線程,這里也可以用Schedulers.newThread(),只不過io線程可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率。前面的代碼根據(jù)異步和鏈?zhǔn)骄幊痰脑瓌t,我們可以寫成

 Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onNext("3");
                emitter.onComplete();
            }
        })
                .observeOn(AndroidSchedulers.mainThread())//回調(diào)在主線程
                .subscribeOn(Schedulers.io())//執(zhí)行在io線程
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e(TAG,"onSubscribe");
                    }
                    @Override
                    public void onNext(String value) {
                        Log.e(TAG,"onNext:"+value);
                    }
                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG,"onError="+e.getMessage());
                    }

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

關(guān)于Retrofit的

Retrofit其實我們可以理解為OkHttp的加強(qiáng)版,它也是一個網(wǎng)絡(luò)加載框架。底層是使用OKHttp封裝的。準(zhǔn)確來說,網(wǎng)絡(luò)請求的工作本質(zhì)上是OkHttp完成,而 Retrofit 僅負(fù)責(zé)網(wǎng)絡(luò)請求接口的封裝。它的一個特點是包含了特別多注解,方便簡化你的代碼量。并且還支持很多的開源庫(著名例子:Retrofit + RxJava)。

優(yōu)點

  • 超級解耦
  • 可以配置不同HttpClient來實現(xiàn)網(wǎng)絡(luò)請求,如OkHttp、HttpClient...
  • 支持同步、異步和RxJava
  • 可以配置不同的反序列化工具來解析數(shù)據(jù),如json、xml...
  • 請求速度快,使用非常方便靈活

使用

1.創(chuàng)建Retrofit對象,采用建造者模式。

Retrofit retrofit = new Retrofit.Builder()
        //設(shè)置baseUrl,baseUrl+接口中配置的地址組成真正的請求地址。
        .baseUrl("http://wanandroid.com/")
        .client(new OkHttpClient())
        .build();

2.創(chuàng)建請求接口,這里是通過注解的方式獲取到請求類型,參數(shù)等信息,所有的請求參數(shù)都可以在這里進(jìn)行配置,然后框架層根據(jù)這些信息封裝成一個Request對象,發(fā)給服務(wù)端

public interface WanAndroidService {
    /**
     * 獲取公眾號列表
     * @Call<ResponseBody>
     */
    @GET("wxarticle/chapters/json")
    //baseUrl+接口中配置的地址組成真正的請求地址。
    Call<ResponseBody> getPublicAccountList();
}

3.創(chuàng)建請求接口對象。

WanAndroidService service = retrofit.create(WanAndroidService.class);
 
 Call<ResponseBody> responseBodyCall = service.getPublicAccountList();

4.發(fā)送

 responseBodyCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    Log.e("玩Android數(shù)據(jù)-------",response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });

兩者怎么結(jié)合呢?

Retrofit retrofit = new Retrofit.Builder()
        //設(shè)置baseUrl,baseUrl+接口中配置的地址組成真正的請求地址。
        .baseUrl("http://wanandroid.com/")
        .client(new OkHttpClient())
        .addConverterFactory(GsonConverterFactory.create()) // 支持Gson解析
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava2
        .build();
public interface WanAndroidService {
    /**
     * 獲取公眾號列表
     * @return  Observable<PublicAccountBean>
     */
    @GET("wxarticle/chapters/json")
    Observable<PublicAccountBean> getPublicAccountList();
}

GsonConverterFactory的作用是將請求的結(jié)果轉(zhuǎn)化成具體的JavaBean。至于Observable,是不是很熟悉?對,它就是RxJava中的被觀察者,RxJava2CallAdapterFactory是將該javaBean的對象再封裝成Observable,中間經(jīng)歷了兩次轉(zhuǎn)化。讓我們看下最終的調(diào)用:

 WanAndroidService service = retrofit.create(WanAndroidService.class);
        service.getPublicAccountList()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<PublicAccountBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(PublicAccountBean publicAccountBean) {
                        //請求成功
                        for (int i = 0; i < publicAccountBean.getData().size(); i++) {
                            Log.e("data----------", publicAccountBean.getData().get(i).getName());
                        }

                    }

                    @Override
                    public void onError(Throwable e) {
                        //失敗
                    }

                    @Override
                    public void onComplete() {
                    }
                });

封裝

封裝net

首先創(chuàng)建一個Retrofit管理類,將Retrofit、OkHttpClient和請求接口的構(gòu)建放一起。

public class RetrofitManager {
    private Retrofit mRetrofit;

    private static class InstanceHelper {
        static RetrofitManager instance = new RetrofitManager();
    }

    public static RetrofitManager getInstance() {
        return InstanceHelper.instance;
    }

    private RetrofitManager() {
        mRetrofit = new Retrofit.Builder()
                //設(shè)置baseUrl
                .baseUrl("http://wanandroid.com/")
                //設(shè)置OkHttpClient對象
                .client(createOkhttpClient())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
                .addConverterFactory(GsonConverterFactory.create()) // 支持Gson解析
                .addConverterFactory(ScalarsConverterFactory.create())//支持字符串
                .build();
    }

    /*
    * 創(chuàng)建OkHttpClient對象。Retrofit底層基于OkHttpClient進(jìn)行網(wǎng)絡(luò)請求。
    * */
    private OkHttpClient createOkhttpClient() {
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
        return new OkHttpClient.Builder()
                //設(shè)置連接超時時間
                .connectTimeout(30, TimeUnit.SECONDS)
                //設(shè)置讀取超時時間
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                //添加日志過濾器
                .addInterceptor(httpLoggingInterceptor)
                //添加BaseInterceptor過濾器
                .addInterceptor(new BaseInterceptor())
                .build();
    }

    public <T> T createApi(final Class<T> service) {
        return mRetrofit.create(service);
    }
}

接著是創(chuàng)建請求接口API
三行代碼完成get post設(shè)置,被監(jiān)聽的設(shè)置,參數(shù)的設(shè)置 。

public interface API {
    /**
     * 獲取公眾號列表
     * @return  Observable<PublicAccountBean>
     */
    @POST("wxarticle/chapters/json")
    @FormUrlEncoded
    Observable<PublicAccountBean> getPublicAccountList(@FieldMap Map<String, String> map);
}

BaseInterceptor是用來添加公共參數(shù)和頭部等,get和post方法添加的方法不一樣所以要區(qū)分。

public class BaseInterceptor implements Interceptor {
//    這里分了POST和GET等其它請求,POST和GET添加請求頭和添加參數(shù)的代碼不同,所以得判斷請求的method。
    @NonNull
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        //POST請求
        if (request.method().equals("POST")) {
            FormBody formBody = null;
            FormBody.Builder bodyBuilder = new FormBody.Builder();
            if (request.body() instanceof FormBody) {
                formBody = (FormBody) request.body();
                //把原來的參數(shù)添加到新的構(gòu)造器,(因為沒找到直接添加,所以就new新的)
                for (int i = 0; i < formBody.size(); i++) {
                    bodyBuilder.add(formBody.name(i), formBody.value(i));
                }
                //添加公共參數(shù)
                formBody = bodyBuilder
                        .add("pubParam1", "1")
                        .add("pubParam2", "2")
                        .add("pubParam3", "3")
                        .build();

                //添加請求頭
                request = request
                        .newBuilder()
                        .post(formBody)
                        .addHeader("Content-Type", "application/json;charset=UTF-8")
                        .addHeader("User-Agent", "android")
                        .build();
            }
            return chain.proceed(request);
        } else {
            //添加公共參數(shù)
            HttpUrl.Builder urlBuilder = request.url()
                    .newBuilder()
                    .addQueryParameter("pubParam1", "1")
                    .addQueryParameter("pubParam2", "2")
                    .addQueryParameter("pubParam3", "3");

            //添加請求頭
            Request.Builder newBuilder = request.newBuilder()
                    .method(request.method(), request.body())
                    .url(urlBuilder.build())
                    .addHeader("Content-Type", "application/json;charset=UTF-8")
                    .addHeader("User-Agent", "android");

            return chain.proceed(newBuilder.build());
        }

    }

}

框架搭建差不多就是這樣了。之后就是直接使用就行啦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容