Retrofit2+Rxjava2+okHttp 網路框架封裝
說明
RxJava的概念其實很模糊,我對它的理解就是一個給你方便處理非同步問題的框架,到底有多方便,體會過才知道。。。
Retrofit就是對okhttp做了一層封裝。把網路請求都交給給了Okhttp,我們只需要通過簡單的配置就能使用retrofit來進行網路請求了,Retrofit 除了提供了傳統的 Callback 形式的 API,還有 RxJava 版本的 Observable 形式 API。
自己整理資料當做筆記
一,需要新增的依賴包
compile 'io.reactivex.rxjava2:rxjava:2.0.7' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' compile 'com.jakewharton:butterknife:8.4.0'
二、網上找了一個url練習具體是http://gank.io/api/data/福利/10/1
1.根據返回引數,封裝一個基類baseresult (根據實際情況而定)
package com.example.rxjavaretrofit.base; /** * Created by fg on 2017/7/25. * 解析實體基類 */ public class BaseResult<T> { private static int SUCCESS_CODE=000000;//成功的code private int code; private String message; private T results; private boolean error; public boolean isSuccess(){ return getCode()==SUCCESS_CODE; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getResults() { return results; } public void setResults(T results) { this.results = results; } public boolean isError() { return error; } public void setError(boolean error) { this.error = error; } @Override public String toString() { return super.toString(); } }
2.把result內的返回資料 通過GsonFormet工具生成實體類 Bean
package com.example.rxjavaretrofit.bean; /** * Created by 付剛 on 2018/7/25. */ public class MeiZiBean { /** * _id : 5b50107f421aa917a31c0565 * createdAt : 2018-07-19T12:15:59.226Z * desc : 2018-07-19 * publishedAt : 2018-07-19T00:00:00.0Z * source : web * type : 福利 * url : https://ww1.sinaimg.cn/large/0065oQSqly1ftf1snjrjuj30se10r1kx.jpg * used : true * who : lijinshanmx */ private String _id; private String createdAt; private String desc; private String publishedAt; private String source; private String type; private String url; private boolean used; private String who; public String get_id() { return _id; } public void set_id(String _id) { this._id = _id; } public String getCreatedAt() { return createdAt; } public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getPublishedAt() { return publishedAt; } public void setPublishedAt(String publishedAt) { this.publishedAt = publishedAt; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public boolean isUsed() { return used; } public void setUsed(boolean used) { this.used = used; } public String getWho() { return who; } public void setWho(String who) { this.who = who; } }
如果需要實現序列化進行傳值 可實現Parcelable或者Serializable介面
3.接下來我們就要開始介面了哦,回到我們上面的ApiService介面模擬一個API介面getMeiZi() 可以返回得到一個observable<Object>。
package com.example.rxjavaretrofit.network;
import com.example.rxjavaretrofit.base.BaseResult;
import com.example.rxjavaretrofit.bean.MeiZiBean;
import java.util.List;
import io.reactivex.Observable;
import retrofit2.http.GET;
/**
* Created by fg on 2018/7/25.
*/
public interface ApiServise {
//網路請求超時時間 單位毫秒
int DEFAULT_TIMEOUT=20000;
String HOST = "http://gank.io/";
String API_SERVER_URL = HOST + "api/data/";
@GET("福利/10/1")
Observable<BaseResult<List<MeiZiBean>>> getMeiZi();
}
4.就是對自己的Retrofit去進行封裝設定
(1)retrofit是基於okhttp的加強版,所以第一步去自定義一個okhttpclient,裡面設定兩個攔截器,一個是日誌攔截器,用於對日誌的篩選,還一個就是網路攔截器,用於對網路請求頭的總體設定。
package com.example.rxjavaretrofit.Utils;
import android.util.Log;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
/**
* Created by fg on 2018/7/25.
* *@description 攔截器工具類
*/
public class InterceptorUtil {
public static String TAG="----";
//日誌攔截器
public static HttpLoggingInterceptor LogInterceptor(){
return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.w(TAG, "log: "+message );
}
}).setLevel(HttpLoggingInterceptor.Level.BODY);//設定列印資料的級別
}
public static Interceptor HeaderInterceptor(){
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request mRequest=chain.request();
//在這裡你可以做一些想做的事,比如token失效時,重新獲取token
//或者新增header等等,PS我會在下一篇文章總寫攔截token方法
return chain.proceed(mRequest);
}
};
}
}
(2)建立一個觀察者基類,在其中進行對請求錯誤的封裝和對進度條顯示與消失的封裝。
package com.example.rxjavaretrofit.base;
import android.accounts.NetworkErrorException;
import android.content.Context;
import com.example.rxjavaretrofit.widget.ProgressDialog;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeoutException;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
/**
* Created by fg on 2018/7/25.
* Observer的封裝
*/
public abstract class BaseObserver<T> implements Observer<BaseResult<T>> {
protected Context mContext;
public BaseObserver(Context cxt) {
this.mContext = cxt;
}
public BaseObserver() {
}
@Override
public void onSubscribe(Disposable d) {
onRequestStart();
}
@Override
public void onNext(BaseResult<T> tBaseEntity) {
onRequestEnd();
if (tBaseEntity.isSuccess()) {
try {
onSuccees(tBaseEntity);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
onCodeError(tBaseEntity);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onError(Throwable e) {
// Log.w(TAG, "onError: ", );這裡可以列印錯誤資訊
onRequestEnd();
try {
if (e instanceof ConnectException
|| e instanceof TimeoutException
|| e instanceof NetworkErrorException
|| e instanceof UnknownHostException) {
onFailure(e, true);
} else {
onFailure(e, false);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
@Override
public void onComplete() {
}
/**
* 返回成功
*
* @param t
* @throws Exception
*/
protected abstract void onSuccees(BaseResult<T> t) throws Exception;
/**
* 返回成功了,但是code錯誤
*
* @param t
* @throws Exception
*/
protected void onCodeError(BaseResult<T> t) throws Exception {
}
/**
* 返回失敗
*
* @param e
* @param isNetWorkError 是否是網路錯誤
* @throws Exception
*/
protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception;
protected void onRequestStart() {
}
protected void onRequestEnd() {
closeProgressDialog();
}
public void showProgressDialog() {
ProgressDialog.show(mContext, false, "請稍後");
}
public void closeProgressDialog() {
ProgressDialog.cancle();
}
}
(3)然後要建立Retrofit例項,構建一個請求的基類
package com.example.rxjavaretrofit.base;
import com.example.rxjavaretrofit.Utils.InterceptorUtil;
import com.example.rxjavaretrofit.network.ApiServise;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by fg on 2018/7/25.
*/
public class BaseRequest {
//retrofit底層用的okHttp,所以設定超時還需要okHttp
//然後設定5秒超時
//其中DEFAULT_TIMEOUT是我這邊定義的一個常量
//TimeUnit為java.util.concurrent包下的時間單位
//TimeUnit.SECONDS這裡為秒的單位
OkHttpClient client=new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)//設定連線超時時間
.readTimeout(20, TimeUnit.SECONDS)//設定讀取超時時間
.writeTimeout(20, TimeUnit.SECONDS)//設定寫入超時時間
.addInterceptor(InterceptorUtil.HeaderInterceptor())//新增其他攔截器
.addInterceptor(InterceptorUtil.LogInterceptor())//新增日誌攔截器
.build();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create()) //新增Gson轉換器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//新增Rx轉換器
.baseUrl(ApiServise.API_SERVER_URL) //baseurl
.client(client)
.build();
public ApiServise apiServise = retrofit.create(ApiServise.class);
private static BaseRequest instance;
public static synchronized BaseRequest getInstance(){
if(instance == null)
instance = new BaseRequest();
return instance;
}
public ApiServise getService() {
return apiServise;
}
}
OK這時候就可以跑通了讓我們看看完整的請求 (observable(被觀察者)和observer(觀察者)相訂閱)
public void getData() {
BaseRequest.getInstance().getService()
.getMeiZi()
.subscribeOn(Schedulers.newThread())
.subscribe(new BaseObserver<List<MeiZiBean>>(this) {
@Override
protected void onSuccees(BaseResult<List<MeiZiBean>> t) throws Exception {
List<MeiZiBean> results = t.getResults();
Log.e("fff",results.size()+"");
}
@Override
protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
Log.e("fff",e.toString());
}
});
}
那麼到這裡,封裝基本上大功告成了,但是上面可以成功解析。後續資料處理就不做敘述了,