RxJava+Retrofit+MVP学习笔记
学习链接,都是跟着大佬一步步来的,本篇主要是自己的笔记
RxJava和Retrofit最近超火,不学不是人。
首先关于RxJava
概念官方定义是罗里吧嗦一大堆看不懂,主要看这两个词就够了,异步,基于事件。
-
观察者设计模式
RxJava是基于观察者和被观察者模式,观察者和被观察者之间存在一种订阅的关系,观察者可以知道被观察者某种事件下所发生的一切。
观察者模式 -
基于事件
你老婆拿着你的工资卡去商场购物,买了一个两万块钱的包包,这时候你就可以收到银行发来的一条消费两万元的短信,这个时候你就是观察者,你老婆就是被观察者。
但你不可能观察你老婆所有的事情吧,比如问了个路、喝了杯咖啡等等,这些你老婆不告诉你你是不会知道的,你能知道的仅仅是你老婆花了两万块钱买了个很贵的包而已。
凡是你卡里余额变动,你都能知道,我们可以说这是基于银行卡余额变动事件下的观察者模式。总结四个字:基于事件。 -
异步
RxJava它是异步的。这个比较好理解,就好像我去蛋糕店买蛋糕,我跟老板说了我想要什么样的蛋糕,然后我告诉老板我什么时候来取,不必一直在蛋糕店里等着,我可以去忙其它的事,这就是异步。 -
操作符转变
被观察者是可以通过某种操作符转变的,就是用一个操作符可以把被观察者改变的意思.....
RxJava中也内置了许多操作符,可以把被观察者进行转变,转变为另外一种形态以后在研究..
创建一个观察者模式
1.创建被观察者。
ObservableEmitter有三种的方法,
- void onNext(T value),方法可以无限调用
- void onError(Throwable error),不可以重复调用
- void onComplete(),OnComplete可以重复调用,但是Observer(观察者)只会接收一次
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
//把这个消息发送出去。
emitter.onNext("我花了两万块钱买了个包");
}
});
2.创建观察者。
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的异步和链式编程
前言里面有提到,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<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("1");
emitter.onNext("2");
emitter.onNext("3");
emitter.onComplete();
}
})
.observeOn(AndroidSchedulers.mainThread())//回调在主线程
.subscribeOn(Schedulers.io())//执行在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()");
}
});
关于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<ResponseBody>
*/
@GET("wxarticle/chapters/json")
//baseUrl+接口中配置的地址组成真正的请求地址。
Call<ResponseBody> getPublicAccountList();
}
3.创建请求接口对象。
WanAndroidService service = retrofit.create(WanAndroidService.class);
Call<ResponseBody> responseBodyCall = service.getPublicAccountList();
4.发送
responseBodyCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.e("玩Android数据-------",response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> 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<PublicAccountBean>
*/
@GET("wxarticle/chapters/json")
Observable<PublicAccountBean> 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<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首先创建一个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> T createApi(final Class<T> service) {
return mRetrofit.create(service);
}
}
接着是创建请求接口API
三行代码完成get post设置,被监听的设置,参数的设置 。
public interface API {
/**
* 获取公众号列表
* @return Observable<PublicAccountBean>
*/
@POST("wxarticle/chapters/json")
@FormUrlEncoded
Observable<PublicAccountBean> getPublicAccountList(@FieldMap Map<String, String> 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());
}
}
}
框架搭建差不多就是这样了。之后就是直接使用就行啦。