RxJava+Retrofit+MVP学习笔记

学习链接,都是跟着大佬一步步来的,本篇主要是自己的笔记
RxJava和Retrofit最近超火,不学不是人。

首先关于RxJava

概念

官方定义是罗里吧嗦一大堆看不懂,主要看这两个词就够了,异步,基于事件。

  • 观察者设计模式
    RxJava是基于观察者和被观察者模式,观察者和被观察者之间存在一种订阅的关系,观察者可以知道被观察者某种事件下所发生的一切。


    观察者模式
  • 基于事件
    你老婆拿着你的工资卡去商场购物,买了一个两万块钱的包包,这时候你就可以收到银行发来的一条消费两万元的短信,这个时候你就是观察者,你老婆就是被观察者。
    但你不可能观察你老婆所有的事情吧,比如问了个路、喝了杯咖啡等等,这些你老婆不告诉你你是不会知道的,你能知道的仅仅是你老婆花了两万块钱买了个很贵的包而已。
    凡是你卡里余额变动,你都能知道,我们可以说这是基于银行卡余额变动事件下的观察者模式。总结四个字:基于事件。

  • 异步
    RxJava它是异步的。这个比较好理解,就好像我去蛋糕店买蛋糕,我跟老板说了我想要什么样的蛋糕,然后我告诉老板我什么时候来取,不必一直在蛋糕店里等着,我可以去忙其它的事,这就是异步。

  • 操作符转变
    被观察者是可以通过某种操作符转变的,就是用一个操作符可以把被观察者改变的意思.....
    RxJava中也内置了许多操作符,可以把被观察者进行转变,转变为另外一种形态以后在研究..

创建一个观察者模式

1.创建被观察者。
ObservableEmitter有三种的方法,

  • void onNext(T value),方法可以无限调用
  • void onError(Throwable error),不可以重复调用
  • void onComplete(),OnComplete可以重复调用,但是Observer(观察者)只会接收一次
Observable observable = Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                 //把这个消息发送出去。
                emitter.onNext("我花了两万块钱买了个包");
            }
        });

2.创建观察者。

Observer observer = new Observer() {
            @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的异步和链式编程

前言里面有提到,RxJava是支持异步的
需要Scheduler。Scheduler,英文名调度器,它是RxJava用来控制线程。
当我们没有设置的时候,RxJava遵循哪个线程产生就在哪个线程消费的原则,也就是说线程不会产生变化,始终在同一个。
RxJava后台执行,前台调用,这个原则,我们需要调用observeOn(AndroidSchedulers.mainThread()),observeOn是事件回调的线程,AndroidSchedulers.mainThread()一看就知道是主线程,subscribeOn(Schedulers.io()),subscribeOn是事件执行的线程,Schedulers.io()是子线程,这里也可以用Schedulers.newThread(),只不过io线程可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。前面的代码根据异步和链式编程的原则,我们可以写成

 Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext("1");
                emitter.onNext("2");
                emitter.onNext("3");
                emitter.onComplete();
            }
        })
                .observeOn(AndroidSchedulers.mainThread())//回调在主线程
                .subscribeOn(Schedulers.io())//执行在io线程
                .subscribe(new Observer() {
                    @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()");
                    }
                });

关于Retrofit的

Retrofit其实我们可以理解为OkHttp的加强版,它也是一个网络加载框架。底层是使用OKHttp封装的。准确来说,网络请求的工作本质上是OkHttp完成,而 Retrofit 仅负责网络请求接口的封装。它的一个特点是包含了特别多注解,方便简化你的代码量。并且还支持很多的开源库(著名例子:Retrofit + RxJava)。

优点

  • 超级解耦
  • 可以配置不同HttpClient来实现网络请求,如OkHttp、HttpClient...
  • 支持同步、异步和RxJava
  • 可以配置不同的反序列化工具来解析数据,如json、xml...
  • 请求速度快,使用非常方便灵活

使用

1.创建Retrofit对象,采用建造者模式。

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

2.创建请求接口,这里是通过注解的方式获取到请求类型,参数等信息,所有的请求参数都可以在这里进行配置,然后框架层根据这些信息封装成一个Request对象,发给服务端

public interface WanAndroidService {
    /**
     * 获取公众号列表
     * @Call
     */
    @GET("wxarticle/chapters/json")
    //baseUrl+接口中配置的地址组成真正的请求地址。
    Call getPublicAccountList();
}

3.创建请求接口对象。

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

4.发送

 responseBodyCall.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                try {
                    Log.e("玩Android数据-------",response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

            }
        });

两者怎么结合呢?

Retrofit retrofit = new Retrofit.Builder()
        //设置baseUrl,baseUrl+接口中配置的地址组成真正的请求地址。
        .baseUrl("http://wanandroid.com/")
        .client(new OkHttpClient())
        .addConverterFactory(GsonConverterFactory.create()) // 支持Gson解析
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava2
        .build();
public interface WanAndroidService {
    /**
     * 获取公众号列表
     * @return  Observable
     */
    @GET("wxarticle/chapters/json")
    Observable getPublicAccountList();
}

GsonConverterFactory的作用是将请求的结果转化成具体的JavaBean。至于Observable,是不是很熟悉?对,它就是RxJava中的被观察者,RxJava2CallAdapterFactory是将该javaBean的对象再封装成Observable,中间经历了两次转化。让我们看下最终的调用:

 WanAndroidService service = retrofit.create(WanAndroidService.class);
        service.getPublicAccountList()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @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

首先创建一个Retrofit管理类,将Retrofit、OkHttpClient和请求接口的构建放一起。

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()
                //设置baseUrl
                .baseUrl("http://wanandroid.com/")
                //设置OkHttpClient对象
                .client(createOkhttpClient())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
                .addConverterFactory(GsonConverterFactory.create()) // 支持Gson解析
                .addConverterFactory(ScalarsConverterFactory.create())//支持字符串
                .build();
    }

    /*
    * 创建OkHttpClient对象。Retrofit底层基于OkHttpClient进行网络请求。
    * */
    private OkHttpClient createOkhttpClient() {
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
        return new OkHttpClient.Builder()
                //设置连接超时时间
                .connectTimeout(30, TimeUnit.SECONDS)
                //设置读取超时时间
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                //添加日志过滤器
                .addInterceptor(httpLoggingInterceptor)
                //添加BaseInterceptor过滤器
                .addInterceptor(new BaseInterceptor())
                .build();
    }

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

接着是创建请求接口API
三行代码完成get post设置,被监听的设置,参数的设置 。

public interface API {
    /**
     * 获取公众号列表
     * @return  Observable
     */
    @POST("wxarticle/chapters/json")
    @FormUrlEncoded
    Observable getPublicAccountList(@FieldMap Map map);
}

BaseInterceptor是用来添加公共参数和头部等,get和post方法添加的方法不一样所以要区分。

public class BaseInterceptor implements Interceptor {
//    这里分了POST和GET等其它请求,POST和GET添加请求头和添加参数的代码不同,所以得判断请求的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();
                //把原来的参数添加到新的构造器,(因为没找到直接添加,所以就new新的)
                for (int i = 0; i < formBody.size(); i++) {
                    bodyBuilder.add(formBody.name(i), formBody.value(i));
                }
                //添加公共参数
                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 {
            //添加公共参数
            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());
        }

    }

}

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

你可能感兴趣的:(RxJava+Retrofit+MVP学习笔记)