美文网首页
Retrofit使用教程:组合RxJava简易封装使用

Retrofit使用教程:组合RxJava简易封装使用

作者: x小明 | 来源:发表于2016-12-08 17:25 被阅读0次

本文将围绕Retrofit的组装请求管理器、发起请求、请求响应的封装进行介绍。
以获取手机号码归属地的整个流程为例:

Get请求

请求API类,这个类等待Retrofit通过动态代理的方式将这个接口的方法以及对应得注解生成一个http请求,在把这个http请求交给OkHttp处理。

public interface HttpService {
    @GET(GlobalVar.NetPorts.WEATHER)
    Observable <HttpResult<PhoneLocalBean>> queryWeather(@QueryMap Map<String, String> options);
}

请求管理器

创建一个请求管理器用来配置Retrofit与OkHttp的基本属性。

public class HttpManager {

    public static final String SERVER = GlobalVar.SERVER; //服务器根地址
    private HttpService mHttpService;
    private Retrofit mAdapter;
    private static HttpManager instance;

    private HttpManager() {
        mAdapter = new Retrofit.Builder().baseUrl(SERVER).addConverterFactory(ScalarsConverterFactory.create()).addConverterFactory(GsonDConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).client(getBuilder().build()).build();
    }

    public static HttpManager getInstance() {
        if (instance == null) {
            instance = new HttpManager();
        }
        return instance;
    }

    public HttpService sendRequest() {
        if (mHttpService == null) {
            mHttpService = mAdapter.create(HttpService.class);
        }
        return mHttpService;
    }

    private OkHttpClient.Builder getBuilder() {
        //这里的存储位置只是简单获取,根据实际需要修改
        File cacheFile = new File(BaseApplication.getContext().getCacheDir().getAbsolutePath(), "ShopHttpCache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100);

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addInterceptor(new HttpCacheInterceptor());
        builder.cache(cache);
        builder.readTimeout(GlobalVar.READ_TIMEOUT, TimeUnit.SECONDS);
        builder.connectTimeout(GlobalVar.CONNECT_TIMEOUT, TimeUnit.SECONDS);
        builder.writeTimeout(GlobalVar.WRITE_TIMEOUT, TimeUnit.SECONDS);
        builder.retryOnConnectionFailure(true);
        return builder;
    }
}

请求拦截器

用于对请求的发起与响应的拦截,这里我们可以增加统一的Header,客户端与服务端的加密验证也可以放在这里,网络缓存等等。

public class HttpCacheInterceptor implements Interceptor {

    private static final String TAG = "HttpManager";

    @Override public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        Request.Builder requestBuilder = original.newBuilder().method(original.method(), original.body());

        Headers.Builder hb = new Headers.Builder();
        addHeader(hb);
        if (!NetUtils.isConnected(BaseApplication.getContext())) {
            //网络不可用
            requestBuilder.cacheControl(CacheControl.FORCE_CACHE);
        } else { 
            requestBuilder.cacheControl(CacheControl.FORCE_NETWORK);
        }
        Request request = requestBuilder.headers(hb.build()).build();
        Log.d(TAG, "地址:" + request.url());

        try {
            Response response = chain.proceed(request);
            String cookie = response.headers().get("Set-Cookie");

            if (NetUtils.isConnected(BaseApplication.getContext())) { //如果网络可用
                int maxAge = 60 * 3;
                response = response.newBuilder().removeHeader("Pragma").header("Cache-Control", "public, max-age=" + maxAge).build();
            } else {
                int maxStale = 60 * 60 * 24;
                response = response.newBuilder().removeHeader("Pragma").header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale).build();
            }
            return response;
        } catch(Exception err) {
            Log.e("HttpManager", "http=============" + err.getLocalizedMessage());
        }
        return null;
    }

    private void addHeader(Headers.Builder header) {
        header.add("apikey", "8ca4b101096587f725ff69a07ff4d188");
    }
}

发起请求

这里的addMainSubscription用于简化书写并统一管理发起的订阅,当Activity退出时统一取消订阅。

@Override
public void queryWeather(String phone) {
    Map < String, String > options = new HashMap < >();
    options.put("phone", phone);
    addMainSubscription(HttpManager.getInstance().sendRequest().queryWeather(options), new HttpResultCallBack<PhoneLocalBean> () {

        @Override public void onResponse(PhoneLocalBean bean, int status) {
            if (bean != null) {
                mView.onUserLoadCompleted(bean);
            } else {
                mView.onUserLoadError();
            }
        }

        @Override public void onErr(String err, int status) {
            mView.showToast(err);
            mView.onUserLoadError();
        }
    });
}

自定义请求响应回调

对响应数据成功失败的封装,而一般的数据返回格式基本分为:
1、状态码
2、提示信息
3、具体数据内容
具体数据体可以是集合也可以是对象,所以使用了泛型HttpResult<M>统一处理。这里定义的M一方面是告诉GSON我的子数据格式是什么,另一方面用于回调方法中返回对应得数据类型。

public abstract class HttpResultCallBack<M> extends Subscriber <HttpResult<M>> {

    public abstract void onResponse(M m, int status);
    public abstract void onErr(String msg, int status);

    @Override public void onCompleted() {}

    @Override public void onError(Throwable e) {
        if (e != null) {
            if (e instanceof ResultException) {
                ResultException err = (ResultException) e;
                onErr(err.getErrMsg(), GlobalVar.RESULT_UNLOGIN);
            } else {
                onErr("网络异常,请检查网络", GlobalVar.RESULT_UNLOGIN);
                Log.d("HttpManager", "解析失败==:" + e.getMessage());
            }
        }
        onCompleted();
    }

    private void onHttpFail(String msg, int status) {
        onErr(msg, status);
    }

    @Override public void onNext(HttpResult < M > result) {
        String jsonResponse = new Gson().toJson(result);
        Log.d("HttpManager", "返回ok==:" + jsonResponse);
        if (result.getErrNum() == GlobalVar.RESULT_OK) {
            onResponse(result.getRetData(), GlobalVar.RESULT_OK);
        } else {
            onHttpFail(result.getErrMsg(), GlobalVar.RESULT_UNLOGIN);
        }
    }
}

结语

这里的代码都是结合具体项目来写的,虽然是抽出来的精简版但更容易读懂。我觉得直接看代码更容易理解一段代码的思想,所以大多都是以代码为主注释为辅。最后有哪些不足的地方也谢谢大家指出来~

github源码下载

相关文章

网友评论

      本文标题:Retrofit使用教程:组合RxJava简易封装使用

      本文链接:https://www.haomeiwen.com/subject/utfjmttx.html