打造属于自己的网络请求框架(OKHttp+Retrofit+RxJava)

来源:互联网 发布:仿真设计软件 编辑:程序博客网 时间:2024/05/19 15:44

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

该框架使用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


0 0
原创粉丝点击