學(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() {
}
});
封裝

首先創(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());
}
}
}
框架搭建差不多就是這樣了。之后就是直接使用就行啦。
