打造属于自己的网络请求框架(OKHttp+Retrofit+RxJava)
2016-12-13 13:34
701 查看
开发者们现在都在使用OkHttp了,在很多借鉴之后,现在也来封装属于自己的网络请求框架。
该框架使用Retrofit,OkHttp,RxJava,RxAndroid,Gson一起封装。
客户端请求一般分为如下几步:
通过API向服务器发送请求------->服务器收到请求然后响应(这里有两种情况,一是请求成功返回Json数据,二是去请求失败返回失败状态)---------->客服端拿到服务器返回状态解析数据或者请求失败提示用户
根据以上思路来看代码:
LocalApi是什么呢,在这个类里面我们定义请求方法,get,post等等,
请求发出去了,看一下怎么解析返回的json数据呢,自定义ResponseConverterFactory继承自Converter.Factory
这里解释一下:
在开始写后台的时候最好定好规范,以免造成不必要的麻烦。以上格式只是参考,使用者可自行修改。
我们也可以跟服务器约定错误类型,捕获异常:
代码里面都注释很清楚。
最后在Activity怎么调用呢,直接贴代码:
项目已上传:https://github.com/hedongBlog/MyNetHttp
该框架使用Retrofit,OkHttp,RxJava,RxAndroid,Gson一起封装。
客户端请求一般分为如下几步:
通过API向服务器发送请求------->服务器收到请求然后响应(这里有两种情况,一是请求成功返回Json数据,二是去请求失败返回失败状态)---------->客服端拿到服务器返回状态解析数据或者请求失败提示用户
根据以上思路来看代码:
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() { @Override public 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等等,
public interface LocalApi { //获取类别 @GET("classify") Observable<List<HealthClassifyBean>> getHealthClassify(); }
请求发出去了,看一下怎么解析返回的json数据呢,自定义ResponseConverterFactory继承自Converter.Factory
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; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return new GsonResponseBodyConverter<>(gson, type); } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return new GsonResponseBodyConverter<>(gson, type); } }这只是跟Retrofit绑定,真正的拿到数据,解析的json的在下面:
/** * 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 */ @Override public 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; } } }
这里解释一下:
在开始写后台的时候最好定好规范,以免造成不必要的麻烦。以上格式只是参考,使用者可自行修改。
我们也可以跟服务器约定错误类型,捕获异常:
/** * 用于捕获服务器约定的错误类型 */ 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请求对应的状态码:
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() { } @Override public 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); @Override public void onCompleted() { } @Override public void onNext(T t) { onDone(t); } }
代码里面都注释很清楚。
最后在Activity怎么调用呢,直接贴代码:
private void requestData() { LocalService.getApi().getHealthClassify() .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new AbsAPICallback<List<HealthClassifyBean>>() { @Override protected void onDone(List<HealthClassifyBean> list) { //请求成功,做相应的页面操作 } @Override public void onError(Throwable e) { super.onError(e); //e.getMessage() 可获取服务器返回错误信息 } }); }ok,到此就结束了。
项目已上传:https://github.com/hedongBlog/MyNetHttp
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件