讓初學者把Rxjava+Retrofit先跑起來
這是一篇淺顯的Rxjava+Retrofit文章,從初學者出發,感覺如果工作中沒有充足發揮自學技能的專案,直接去看大佬們寫的很深入的講解,特別容易遺忘、懵甚至不理解,所以我決定寫一篇淺顯的使用Rxjava+Retrofit的文章。
所需依賴庫:
compile"io.reactivex.rxjava2:rxjava:2.1.1" compile'io.reactivex.rxjava2:rxandroid:2.0.2' compile'com.squareup.retrofit2:retrofit:2.3.0' compile'com.squareup.retrofit2:converter-gson:2.3.0' compile'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
一、 retrofit的使用
首先我們要先了解一下retrofit,他是這個組合負責網路訪問的部分,獲取rxjava的被觀察者。
1. 根據要訪問的資料建立實體類,我訪問的是“聚合資料”提供的新聞頭條連結(“http://v.juhe.cn/toutiao/index?type=top&key=APPKEY”),獲取的資料格式為:
根據資料建立實體類:
public class NewsBeen<T> { @SerializedName("reason") private String reason; @SerializedName("result") private T result; @SerializedName("error_code") private int error_code; public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public T getResult() { return result; } public void setResult(T result) { this.result = result; } public int getError_code() { return error_code; } public void setError_code(int error_code) { this.error_code = error_code; } }
public class ResultBean { private String stat; private List<DataBean> data; public String getStat() { return stat; } public void setStat(String stat) { this.stat = stat; } public List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } public static class DataBean { private String uniquekey; private String title; private String date; private String category; private String author_name; private String url; private String thumbnail_pic_s; private String thumbnail_pic_s02; private String thumbnail_pic_s03; public String getUniquekey() { return uniquekey; } public void setUniquekey(String uniquekey) { this.uniquekey = uniquekey; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getAuthor_name() { return author_name; } public void setAuthor_name(String author_name) { this.author_name = author_name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getThumbnail_pic_s() { return thumbnail_pic_s; } public void setThumbnail_pic_s(String thumbnail_pic_s) { this.thumbnail_pic_s = thumbnail_pic_s; } public String getThumbnail_pic_s02() { return thumbnail_pic_s02; } public void setThumbnail_pic_s02(String thumbnail_pic_s02) { this.thumbnail_pic_s02 = thumbnail_pic_s02; } public String getThumbnail_pic_s03() { return thumbnail_pic_s03; } public void setThumbnail_pic_s03(String thumbnail_pic_s03) { this.thumbnail_pic_s03 = thumbnail_pic_s03; } } }
實體類建立沒什麼好說的,可以直接拿引數GsonFormat一下就好了。
2. 然後定義介面
public interface NewsService {
@GET("index")
Observable<NewsBeen<ResultBean>> getNews(@Query("type") String type, @Query("key") String ley);
@GET("index?type=top&key=28aa4ac2a689c881a4e6e51cf918d695")
Observable<NewsBeen<ResultBean>> getNews();
}
介面中兩個方法效果一樣,@後跟網路請求方法,一般為GET和POST,就是GET和POST請求,括號中為拼接的連結,比如這條連結:http://v.juhe.cn/toutiao/index?type=top&key=APPKEY,我們把“http://v.juhe.cn/toutiao/”當做BaseUrl,那請求後括號中的內容加方法引數中的內容拼接起來就是要訪問的連結,這要注意以下幾點:
1. 其中BaseUrl的結尾必須為“/”,不然請求連結時會報錯。
2. 請求方法後括號可以通過(index/{id})的寫法,在方法引數中獲取id,方法引數的處理為(@Path(”id”) int id),比如傳過來123,則此回撥與baseurl拼接的連結就為“index/123”。
3. 如果連結為http://v.juhe.cn/toutiao/index?type=top&key=APPKEY,除了傻瓜式把後邊全放到請求方法後,也可以像方法一中那樣更加靈活的獲取:(@Query("type")String type, @Query("key")String ley);
注:像@Paht和@Query這些註解的具體使用可以在走通整個網路框架後再去慢慢學習瞭解,如果當前正在處理一個專案,且所需要的網路連線比較特殊,也可以專門去搜一下這塊。
3.接下來定義一個OkHttpClient,進行一些訪問配置。
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {//新增網路訪問Header
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("token", "123");
return chain.proceed(builder.build());
}
})
.addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
//獲取網路訪問錯誤資訊
}
}).setLevel(HttpLoggingInterceptor.Level.BASIC))
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)//連結超時
.readTimeout(TIMEOUT,TimeUnit.SECONDS)//讀取超時
.build();
一般使用retrofit訪問網路需要新增如上程式碼中的HttpLoggingInterceptor簡化除錯,需新增依賴:
compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
4. 獲取介面類
NewsService service = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(buildGson()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(httpClient)
.build()
.create(NewsService.class);
.addConverterFactory(GsonConverterFactory.create(buildGson()))這句程式碼是通過gson解析網路獲取的資料,不加應該是會報錯的,其中Gson的定義:
Gson buildGson() = GsonBuilder()
.serializeNulls()
.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
.create();
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())這句程式碼是新增對Rxjava2的支援,注意是Rxjava2,如果整合的是Rxjava要對應修改這裡。
5. 最後通過介面返回Rxjava的被觀察者
Observable<NewsBeen<ResultBean>> observable = RetrofitFactory.getNews().getNews("top", "123456");
這樣Retrofit的工作就完成了,接下來就看Rxjava部分,Rxjava同樣是很優秀內容很多的框架,這次就先依著簡單的實現效果看一下。
二、 Rxjava的使用
Rxjava主要分三部分,被觀察者(Observable)、觀察者(Observer)和連結二者的subscribe(),當被觀察者(Observable)和觀察者(Observer)被subscribe()連結起來的時候,如果被觀察者(Observable)發生變化,被觀察者(Observable)就能感知得到,這這篇文章中就是,當retrofit網路訪問獲取到資料的時候,被觀察者(Observable)獲取得到例項,觀察者(Observer)觀察者就能收到此訊息,處理被觀察中例項中獲取的資料。
1. 剛才我們獲取了被觀察者(Observable),現在我們再來定義一個觀察者
public abstract class BaseObserver<T> implements Observer<NewsBeen<T>> {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull NewsBeen<T> tNewsBeen) {
if (tNewsBeen.getError_code()==0) {
T t = tNewsBeen.getResult();
getDatas (t);
}else {
//在此可處理獲取失敗邏輯
}
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
protected abstract void getDatas(T t);
}
繼承Observer介面,實現其中的方法,建立觀察者基類,成功獲取資料呼叫getDatas(T t)方法將資料傳出去。 2.這樣觀察者和被觀察者都有了,但要注意一點,網路訪問為耗時操作,獲取到資料很多要在主執行緒接收展示,所以要加上執行緒轉換。
public class RxSchedulers {
public static <T> ObservableTransformer<T,T> compose(){
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull Disposable disposable) throws Exception {
//訂閱開始前呼叫,可以在此做一些網路獲取資料環境的判斷
}
})
.observeOn(AndroidSchedulers.mainThread());
}
};
}
}
3.最後把觀察者和被觀察者連結起來。
observable.compose(RxSchedulers.<NewsBeen<ResultBean>>compose()).subscribe(new BaseObserver<ResultBean>(MainActivity.this) {
@Override
protected void getDatas (ResultBean resultBean) {
//最終從自定義的觀察者基類的抽象方法中獲取到網路資料
}
});
經過以上程式碼就可以搭建一個最基本的Rxjava+Retrofit網路框架,誠然,我的水平相比播客中許多大佬的水平要相差甚遠,網上隨便一搜就有很多詳細到原始碼,各種重寫方法的高階播客,感覺那些都不太適合初學者,我的學習方法就是找到一篇簡單的使用播客,先把效果做出來,然後根據效果再去擴充套件著學習,希望我的這篇播客能幫助更多像我一樣,獨自一人向更高艱難前進的人,如果有幸被哪位大佬看見,也希望能獲得指點一二。