当前位置: 代码迷 >> 综合 >> 网络请求框架(OKHttp+Retrofit+RxJava)
  详细解决方案

网络请求框架(OKHttp+Retrofit+RxJava)

热度:40   发布时间:2023-12-13 16:33:59.0

开发者们现在都在使用OkHttp了,在很多借鉴之后,现在也来封装属于自己的网络请求框架。

该框架使用Retrofit,OkHttp,RxJava,RxAndroid,Gson一起封装。

客户端请求一般分为如下几步:

通过API向服务器发送请求——->服务器收到请求然后响应(这里有两种情况,一是请求成功返回Json数据,二是去请求失败返回失败状态)———->客服端拿到服务器返回状态解析数据或者请求失败提示用户

根据以上思路来看代码:

[java] view plain copy
print?
  1. import android.os.Build;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.concurrent.TimeUnit;  
  5.   
  6. import okhttp3.Interceptor;  
  7. import okhttp3.OkHttpClient;  
  8. import okhttp3.Request;  
  9. import okhttp3.Response;  
  10. import okhttp3.logging.HttpLoggingInterceptor;  
  11. import retrofit2.Retrofit;  
  12. import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;  
  13.   
  14. /** 
  15.  * Created by hedong on 2016/4/19. 
  16.  */  
  17. public class LocalService {  
  18.     public static final String API_BASE_URL = “http://www.tngou.net/api/info/”;//主Api路径  
  19.   
  20.     private static final LocalApi service = getRetrofit().create(LocalApi.class);  
  21.   
  22.     private static Retrofit mRetrofit;  
  23.     private static OkHttpClient mOkHttpClient;  
  24.   
  25.     public final static int CONNECT_TIMEOUT = 60;        //设置连接超时时间  
  26.     public final static int READ_TIMEOUT = 60;            //设置读取超时时间  
  27.     public final static int WRITE_TIMEOUT = 60;           //设置写的超时时间  
  28.   
  29.     private static OkHttpClient genericClient() {  
  30.         HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();  
  31.         interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);  
  32.   
  33.         OkHttpClient httpClient = new OkHttpClient.Builder()  
  34.                 .addNetworkInterceptor(interceptor)  
  35.                 .retryOnConnectionFailure(true)  
  36.                 .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)//设置读取超时时间  
  37.                 .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)//设置写的超时时间  
  38.                 .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)//设置连接超时时间  
  39.                 .addInterceptor(new Interceptor() {  
  40.                     @Override  
  41.                     public Response intercept(Chain chain) throws IOException {  
  42.                         Request request = chain.request()  
  43.                                 .newBuilder()  
  44.                                 .addHeader(”source-terminal”“Android”)   //操作系统名称(注:ios、android)//设备型号  
  45.                                 .addHeader(”device-model”, Build.MODEL)         //设备型号  
  46.                                 .addHeader(”os-version”, Build.VERSION.RELEASE)//操作系统版本号  
  47.                                 //.addHeader(“app-name”, name);//应用名称  
  48.                                 .build();  
  49.                         return chain.proceed(request);  
  50.                     }  
  51.                 }).build();  
  52.         return httpClient;  
  53.     }  
  54.   
  55.     public static LocalApi getApi() {  
  56.         return service;  
  57.     }  
  58.   
  59.     protected static Retrofit getRetrofit() {  
  60.   
  61.         if (null == mRetrofit) {  
  62.             if (null == mOkHttpClient) {  
  63.                 mOkHttpClient = genericClient();  
  64.             }  
  65.   
  66.   
  67.             mRetrofit = new Retrofit.Builder()  
  68.                     .baseUrl(API_BASE_URL)  
  69.                     .addConverterFactory(ResponseConverterFactory.create())  
  70.                     .addCallAdapterFactory(RxJavaCallAdapterFactory.create())  
  71.                     .client(mOkHttpClient)  
  72.                     .build();  
  73.   
  74.         }  
  75.   
  76.         return mRetrofit;  
  77.     }  
  78. }  
import android.os.Build;import java.io.IOException;
import java.util.concurrent.TimeUnit;import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;/*** Created by hedong on 2016/4/19.*/
public class LocalService {public static final String API_BASE_URL = "http://www.tngou.net/api/info/";//主Api路径private static final LocalApi service = getRetrofit().create(LocalApi.class);private static Retrofit mRetrofit;private static OkHttpClient mOkHttpClient;public final static int CONNECT_TIMEOUT = 60;        //设置连接超时时间public final static int READ_TIMEOUT = 60;            //设置读取超时时间public final static int WRITE_TIMEOUT = 60;           //设置写的超时时间private static OkHttpClient genericClient() {HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);OkHttpClient httpClient = new OkHttpClient.Builder().addNetworkInterceptor(interceptor).retryOnConnectionFailure(true).readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)//设置读取超时时间.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)//设置写的超时时间.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)//设置连接超时时间.addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request().newBuilder().addHeader("source-terminal", "Android")   //操作系统名称(注:ios、android)//设备型号.addHeader("device-model", Build.MODEL)         //设备型号.addHeader("os-version", Build.VERSION.RELEASE)//操作系统版本号//.addHeader("app-name", name);//应用名称.build();return chain.proceed(request);}}).build();return httpClient;}public static LocalApi getApi() {return service;}protected static Retrofit getRetrofit() {if (null == mRetrofit) {if (null == mOkHttpClient) {mOkHttpClient = genericClient();}mRetrofit = new Retrofit.Builder().baseUrl(API_BASE_URL).addConverterFactory(ResponseConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).client(mOkHttpClient).build();}return mRetrofit;}
}
注释写的很清楚了,但是在添加header的时候,根据自己需要添加。

LocalApi是什么呢,在这个类里面我们定义请求方法,get,post等等,

[java] view plain copy
print?
  1. public interface LocalApi {  
  2.   
  3.     //获取类别  
  4.     @GET(“classify”)  
  5.     Observable<List<HealthClassifyBean>> getHealthClassify();  
  6.   
  7.   
  8. }  
public interface LocalApi {//获取类别@GET("classify")Observable<List<HealthClassifyBean>> getHealthClassify();}

请求发出去了,看一下怎么解析返回的json数据呢,自定义ResponseConverterFactory继承自Converter.Factory

[java] view plain copy
print?
  1. public class ResponseConverterFactory extends Converter.Factory {  
  2.     public static ResponseConverterFactory create() {  
  3.         return create(new Gson());  
  4.     }  
  5.   
  6.     public static ResponseConverterFactory create(Gson gson) {  
  7.         return new ResponseConverterFactory(gson);  
  8.     }  
  9.   
  10.     private final Gson gson;  
  11.   
  12.     private ResponseConverterFactory(Gson gson) {  
  13.         if (gson == nullthrow new NullPointerException(“gson == null”);  
  14.         this.gson = gson;  
  15.     }  
  16.   
  17.     @Override  
  18.     public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {  
  19.         return new GsonResponseBodyConverter<>(gson, type);  
  20.     }  
  21.   
  22.     @Override  
  23.     public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {  
  24.         return new GsonResponseBodyConverter<>(gson, type);  
  25.     }  
  26. }  
public class ResponseConverterFactory extends Converter.Factory {public static ResponseConverterFactory create() {return create(new Gson());}public static ResponseConverterFactory create(Gson gson) {return new ResponseConverterFactory(gson);}private final Gson gson;private ResponseConverterFactory(Gson gson) {if (gson == null) throw new NullPointerException("gson == null");this.gson = gson;}@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {return new GsonResponseBodyConverter<>(gson, type);}@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {return new GsonResponseBodyConverter<>(gson, type);}
}
这只是跟Retrofit绑定,真正的拿到数据,解析的json的在下面:

[java] view plain copy
print?
  1. /** 
  2.  * Created by hedong on 2016/4/19. 
  3.  */  
  4. public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {  
  5.     private final Gson gson;  
  6.     private final Type type;  
  7.   
  8.     public GsonResponseBodyConverter(Gson gson, Type type) {  
  9.         this.gson = gson;  
  10.         this.type = type;  
  11.     }  
  12.   
  13.     /** 
  14.      * {  
  15.      * “status”: true, 
  16.      * “data”: [ 
  17.      * {  
  18.      * “description”: ”“, 
  19.      * “id”: 6, 
  20.      * “keywords”: ”“, 
  21.      * “name”: ”“, 
  22.      * “seq”: 1, 
  23.      * “title”: ”“ 
  24.      * }, 
  25.      * {  
  26.      * “description”: ”“, 
  27.      * “id”: 5, 
  28.      * “keywords”: ”“, 
  29.      * “name”: ”“, 
  30.      * “seq”: 2, 
  31.      * “title”: ”“ 
  32.      * } 
  33.      * ] 
  34.      * } 
  35.      * 
  36.      * @param value 
  37.      * @return 
  38.      * @throws IOException 
  39.      */  
  40.     @Override  
  41.     public T convert(ResponseBody value) throws IOException {  
  42.         String response = value.string();  
  43.         Log.d(”Network”“response>>” + response);  
  44.         try {  
  45.   
  46.             JSONObject jsonObject = new JSONObject(response);  
  47.             if (jsonObject.getString(“status”).equals(“true”)) {  
  48.                 //result==true表示成功返回,继续用本来的Model类解析  
  49.                 String data = jsonObject.getString(”data”);  
  50.   
  51.                 return gson.fromJson(data, type);  
  52.   
  53.             } else {  
  54.                 //ErrResponse 将msg解析为异常消息文本  
  55.                 ErrResponse errResponse = gson.fromJson(response, ErrResponse.class);  
  56.                 throw new ResultException(0, errResponse.getMsg());  
  57.             }  
  58.   
  59.         } catch (JSONException e) {  
  60.             e.printStackTrace();  
  61.             Log.e(”Network”, e.getMessage());  
  62.             return null;  
  63.         }  
  64.     }  
  65. }  
/*** Created by hedong on 2016/4/19.*/
public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {private final Gson gson;private final Type type;public GsonResponseBodyConverter(Gson gson, Type type) {this.gson = gson;this.type = type;}/*** {* "status": true,* "data": [* {* "description": "",* "id": 6,* "keywords": "",* "name": "",* "seq": 1,* "title": ""* },* {* "description": "",* "id": 5,* "keywords": "",* "name": "",* "seq": 2,* "title": ""* }* ]* }** @param value* @return* @throws IOException*/@Overridepublic T convert(ResponseBody value) throws IOException {String response = value.string();Log.d("Network", "response>>" + response);try {JSONObject jsonObject = new JSONObject(response);if (jsonObject.getString("status").equals("true")) {//result==true表示成功返回,继续用本来的Model类解析String data = jsonObject.getString("data");return gson.fromJson(data, type);} else {//ErrResponse 将msg解析为异常消息文本ErrResponse errResponse = gson.fromJson(response, ErrResponse.class);throw new ResultException(0, errResponse.getMsg());}} catch (JSONException e) {e.printStackTrace();Log.e("Network", e.getMessage());return null;}}
}

这里解释一下:




在开始写后台的时候最好定好规范,以免造成不必要的麻烦。以上格式只是参考,使用者可自行修改。


我们也可以跟服务器约定错误类型,捕获异常:

[java] view plain copy
print?
  1. /** 
  2.  * 用于捕获服务器约定的错误类型 
  3.  */  
  4. public class ResultException extends RuntimeException {  
  5.     private int errCode = 0;  
  6.   
  7.     public ResultException(int errCode, String msg) {  
  8.         super(msg);  
  9.         this.errCode = errCode;  
  10.     }  
  11.   
  12.     public int getErrCode() {  
  13.         return errCode;  
  14.     }  
  15. }  
/*** 用于捕获服务器约定的错误类型*/
public class ResultException extends RuntimeException {private int errCode = 0;public ResultException(int errCode, String msg) {super(msg);this.errCode = errCode;}public int getErrCode() {return errCode;}
}
自定义回调,获取http请求对应的状态码:

[java] view plain copy
print?
  1. public abstract class AbsAPICallback<T> extends Subscriber<T> {  
  2.     //对应HTTP的状态码  
  3.     private static final int UNAUTHORIZED = 401;  
  4.     private static final int FORBIDDEN = 403;  
  5.     private static final int NOT_FOUND = 404;  
  6.     private static final int REQUEST_TIMEOUT = 408;  
  7.     private static final int INTERNAL_SERVER_ERROR = 500;  
  8.     private static final int BAD_GATEWAY = 502;  
  9.     private static final int SERVICE_UNAVAILABLE = 503;  
  10.     private static final int GATEWAY_TIMEOUT = 504;  
  11.   
  12.     protected AbsAPICallback() {  
  13.   
  14.     }  
  15.   
  16.     @Override  
  17.     public void onError(Throwable e) {  
  18.         Throwable throwable = e;  
  19.         //获取最根源的异常  
  20.         while (throwable.getCause() != null) {  
  21.             e = throwable;  
  22.             throwable = throwable.getCause();  
  23.         }  
  24.   
  25.         if (e instanceof HttpException) { //HTTP错误  
  26.             HttpException httpException = (HttpException) e;  
  27.             switch (httpException.code()) {  
  28.                 case UNAUTHORIZED:  
  29.                 case FORBIDDEN:  
  30.                 case NOT_FOUND:  
  31.                 case REQUEST_TIMEOUT:  
  32.                 case GATEWAY_TIMEOUT:  
  33.                 case INTERNAL_SERVER_ERROR:  
  34.                 case BAD_GATEWAY:  
  35.                 case SERVICE_UNAVAILABLE:  
  36.                 default:  
  37.                     //Toast.makeText(App.getInstance(), R.string.server_http_error, Toast.LENGTH_SHORT).show();  
  38.                     break;  
  39.             }  
  40.         } else if (e instanceof SocketTimeoutException) {  
  41.             //Toast.makeText(App.getInstance(), R.string.network_error, Toast.LENGTH_SHORT).show();  
  42.         } else if (e instanceof ResultException) { //服务器返回的错误  
  43.             ResultException resultException = (ResultException) e;  
  44.           //  Toast.makeText(App.getInstance(), resultException.getMessage(), Toast.LENGTH_SHORT).show();  
  45.         } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) {  
  46.            // Toast.makeText(App.getInstance(), R.string.data_error, Toast.LENGTH_SHORT).show(); //均视为解析错误  
  47.         } else if(e instanceof ConnectException){  
  48.            // Toast.makeText(App.getInstance(), R.string.server_http_error, Toast.LENGTH_SHORT).show();  
  49.         } else { //未知错误  
  50.   
  51.         }  
  52.   
  53.         onCompleted();  
  54.     }  
  55.   
  56.     protected abstract void onDone(T t);  
  57.   
  58.     @Override  
  59.     public void onCompleted() {  
  60.   
  61.     }  
  62.   
  63.     @Override  
  64.     public void onNext(T t) {  
  65.         onDone(t);  
  66.     }  
  67. }  
public abstract class AbsAPICallback<T> extends Subscriber<T> {//对应HTTP的状态码private static final int UNAUTHORIZED = 401;private static final int FORBIDDEN = 403;private static final int NOT_FOUND = 404;private static final int REQUEST_TIMEOUT = 408;private static final int INTERNAL_SERVER_ERROR = 500;private static final int BAD_GATEWAY = 502;private static final int SERVICE_UNAVAILABLE = 503;private static final int GATEWAY_TIMEOUT = 504;protected AbsAPICallback() {}@Overridepublic void onError(Throwable e) {Throwable throwable = e;//获取最根源的异常while (throwable.getCause() != null) {e = throwable;throwable = throwable.getCause();}if (e instanceof HttpException) {//HTTP错误HttpException httpException = (HttpException) e;switch (httpException.code()) {case UNAUTHORIZED:case FORBIDDEN:case NOT_FOUND:case REQUEST_TIMEOUT:case GATEWAY_TIMEOUT:case INTERNAL_SERVER_ERROR:case BAD_GATEWAY:case SERVICE_UNAVAILABLE:default://Toast.makeText(App.getInstance(), R.string.server_http_error, Toast.LENGTH_SHORT).show();break;}} else if (e instanceof SocketTimeoutException) {//Toast.makeText(App.getInstance(), R.string.network_error, Toast.LENGTH_SHORT).show();} else if (e instanceof ResultException) {//服务器返回的错误ResultException resultException = (ResultException) e;//  Toast.makeText(App.getInstance(), resultException.getMessage(), Toast.LENGTH_SHORT).show();} else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) {// Toast.makeText(App.getInstance(), R.string.data_error, Toast.LENGTH_SHORT).show(); //均视为解析错误} else if(e instanceof ConnectException){// Toast.makeText(App.getInstance(), R.string.server_http_error, Toast.LENGTH_SHORT).show();} else {//未知错误}onCompleted();}protected abstract void onDone(T t);@Overridepublic void onCompleted() {}@Overridepublic void onNext(T t) {onDone(t);}
}

代码里面都注释很清楚。

最后在Activity怎么调用呢,直接贴代码:

[java] view plain copy
print?
  1. private void requestData() {  
  2.       LocalService.getApi().getHealthClassify()  
  3.               .subscribeOn(Schedulers.io())  
  4.               .observeOn(Schedulers.io())  
  5.               .observeOn(AndroidSchedulers.mainThread())  
  6.               .subscribe(new AbsAPICallback<List<HealthClassifyBean>>() {  
  7.                   @Override  
  8.                   protected void onDone(List<HealthClassifyBean> list) {  
  9.   
  10.                       //请求成功,做相应的页面操作  
  11.   
  12.                   }  
  13.   
  14.                   @Override  
  15.                   public void onError(Throwable e) {  
  16.                       super.onError(e);  
  17.                       //e.getMessage() 可获取服务器返回错误信息  
  18.                   }  
  19.               });  
  20.   }  
  private void requestData() {LocalService.getApi().getHealthClassify().subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new AbsAPICallback<List<HealthClassifyBean>>() {@Overrideprotected void onDone(List<HealthClassifyBean> list) {//请求成功,做相应的页面操作}@Overridepublic void onError(Throwable e) {super.onError(e);//e.getMessage() 可获取服务器返回错误信息}});}
ok,到此就结束了。

项目已上传:https://github.com/hedongBlog/MyNetHttp


转自何东_hd的博客:http://blog.csdn.net/hedong_77/article/details/53607245