目前Retrofit和RxJava结合使用已经是非常普遍了,也是现在最热门的一种网络请求方式,今天我们来聊聊,如何对Retrofit + RxJava 网络请求框架实现二次封装,以供大家在项目中可以应用到,也供大家学习和参考
首先我们先来看看关于Retrofit和RxJava最基本的使用
- 我们需要去定义一个对应接口的Service和返回的实体类
public class Content<T> {
private List<T> list;
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
}
实体类省略....
public interface OrderApi {
@GET("order/findByCustomerIdOrderList")
Observable<List<Order>> findByCustomerIdOrderList(@Query("offset") int offset, @Query("max") int max);
}
2.初始化Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.wanhulian.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
3.使用方式
OrderApi orderApi= retrofit.create(OrderApi.class);
Observable<List<Order>> observable = orderApi.findByCustomerIdOrderList(0,5)
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<GankResultBean>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(GankResultBean gankResultBean) {
}
});
实现起来还是比较简单的,但是如果每次都要写这么一大串代码,是不是觉得很麻烦,而且很不利于后期项目维护。这个时候我就该考虑一下对代码进行封装了。
4.首先我们创建一个RetrofitUtil类,私有化构造函数,里面创建了一个OkHttpClient对象,进行相关信息的配置,然后用单例模式来获取实例
public class RetrofitUtil {
private static RetrofitUtil instance;
private Retrofit retrofit;
private static Gson gson;
private RetrofitUtil(){
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(5000, TimeUnit.MILLISECONDS);
retrofit = new Retrofit.Builder().baseUrl(NetUrl.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(getGson()))
.client(client)
.build();
}
public static RetrofitUtil getInstance(){
if(instance == null){
synchronized (RetrofitUtil.class){
if(instance == null){
instance = new RetrofitUtil();
}
}
}
return instance;
}
public static Gson getGson() {
if (gson == null) {
gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new TypeAdapter<Date>() {
@Override
public void write(JsonWriter out, Date value) throws IOException {
out.value(value == null ? null : value.getTime());
}
@Override
public Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return new Date(in.nextLong());
}
})
.create();
}
return gson;
}
public OrderApi getOrderApi(){
return retrofit.create(OrderApi.class);
}
//获取血压数据
public void findByCustomerIdOrderList(Subscriber<Content<Order>> subscriber, int offset, int max){
Observable<Content<Order>> observable = getOrderApi().findByCustomerIdOrderList( offset, max).map(new HttpResultFunc<Content<Order>>());
toSubscribe(observable,subscriber);
}
private <T> void toSubscribe(Observable<T> o, Subscriber<T> s){
o.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s);
}
/**
* 用来统一处理Http的resultCode,并将HttpResult的Data部分剥离出来返回给subscriber
*
* @param <T> Subscriber真正需要的数据类型,也就是Data部分的数据类型
*/
private class HttpResultFunc<T> implements Func1<KmResult<T>,T> {
@Override
public T call(KmResult<T> kmResult) {
if (kmResult.getErrorCode() == -1) {
throw new ApiException(100);
}
return kmResult.getContent();
}
}
}
这里对KmResult做一个说明,因为后台返回的数据格式一般都是这样的:
{
code:1,
msg:"your message",
data:[]
}
所以我们创建了一个KmResult类,结合HttpResultFunc类,将数据结构里面的 data分离出来
public class KmResult<T> {
private int code;
private String msg;
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.ode = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "KmResult{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
5.接着我们创建了一个ApiException类,主要是对后台返回的code进行处理
public class ApiException extends RuntimeException {
public static final int ERROR_INTERNET = 100;
public ApiException(int resultCode) {
this(getApiExceptionMessage(resultCode));
}
public ApiException(String detailMessage) {
super(detailMessage);
}
/**
* 由于服务器传递过来的错误信息直接给用户看的话,用户未必能够理解
* 需要根据错误码对错误信息进行一个转换,在显示给用户
* @param code
* @return
*/
private static String getApiExceptionMessage(int code){
String message = "";
switch (code) {
case ERROR_INTERNET:
message = "网络不可连接";
break;
default:
message = "未知错误";
}
return message;
}
}
6.然后我们再新建一个MySubscriber类继承Subscriber类,实现onCompleted,onError,onNext三个方法,这样的话我们只需要对onNext方法进行处理。
public class MySubscriber<T> extends Subscriber<T> {
private SubscriberOnNextListener<T> mSubscriberOnNextListener;
private Context mContext;
public MySubscriber(SubscriberOnNextListener<T> subscriberOnNextListener,Context context){
mSubscriberOnNextListener = subscriberOnNextListener;
mContext = context;
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
if (e instanceof SocketTimeoutException) {
Toast.makeText(mContext, "网络中断1,请检查您的网络状态", Toast.LENGTH_SHORT).show();
} else if (e instanceof ConnectException) {
Toast.makeText(mContext, "网络中断2,请检查您的网络状态", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onNext(T t) {
if (mSubscriberOnNextListener != null) {
mSubscriberOnNextListener.onNext(t);
}
}
}
通过接口回调的方式,让调用者自己去实现onNext里面的代码。
public interface SubscriberOnNextListener<T> {
void onNext(T t);
}
7.最后,我们只要通过一两行代码就可以实现网络请求了。
RetrofitUtil.getInstance().findByCustomerIdOrderList(new MySubscriber<>(new SubscriberOnNextListener<Content<Order>>() {
@Override
public void onNext(Content<Order> orderContent) {
List<Order> orderList = orderContent.getList();
}
}, getActivity()),0,5);
}
这个就是我在项目中对Retrofit + RxJava网络请求框架的二次封装,希望对大家对Retrofit + RxJava的学习有所帮助