浅谈Retrofit封装-让框架更加简洁易用
来源:互联网 发布:js数组concat 编辑:程序博客网 时间:2024/05/17 20:32
尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/52329259, 本文出自:【gengqiquan的博客】
不知不觉在在这家公司快三个月了,刚接手项目的时候是真的被里面的代码恶心到了,网络请求用的原生的httpURLconnection。这本来什么,关键是根本就没有进行任何封装。activity里面充斥着大量的handler,要找个oncreated()函数先得把类拉到一半,那种感觉岂止酸爽。由于项目周期紧张。没时间去大规模的重构,新框架只能在新功能里写。采用了retrofit,初期做了简单的封装,断断续续一段时间的优化整理。现在分享出来给大家。
为了方便大家,会形成依赖库。引入和调用方式请看文章底部的github文档
本次封装需要做到的
1支持异步请求统一回调
2参数可配置
3链式调用
4支持基本get和post封装
5支持rxjava返回
6支持一个接口Service 对应一种请求类型,而不是每个API都需要去定义一个接口方法
7支持取消单个请求
8支持请求打标签,退出页面时取消当前页面所有请求
9支持动态配置缓存,缓存与具体的请求接口绑定,
10支持追加统一参数,登录信息token、设备号等
11支持接口版本号配置
12流式下载文件,取消下载请求
下面我们来看下封装过程,博客底部会贴出示例项目地址
retrofit独树一帜的把请求采用了接口,方法和注解参数(parameter annotations)来声明式定义一个请求应该如何被创建的方式。
像这样
public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> contributors(@Path("owner") String owner, @Path("repo") String repo);
然后去实例化并且调用请求
GitHub github = restAdapter.create(GitHub.class); // Fetch and print a list of the contributors to this library. List<Contributor> contributors = github.contributors("square", "retrofit");
先不谈retrofit到底做了多少优化、性能上有多少提升。光是这样的调用方式我就受不了。我特么得写多少个 像上面的GitHub 一样的Service,就算是把url注解方法都写在一个里面,那也得多少行?一个项目六七十行应该是没什么问题的了。嗯。反正我会看疯了的。而且这样的一种调用方式是直接面向框架层的,以后万一我们换框架了怎么办?代码挨个找出来全换一边?你疯不疯?
那我们有没有什么办法改变他?很简单,我们在框架外面再套一层通用框架,作为框架的设计者,我们应该让调用者知道怎么调用就可以了,而不应该让调用者去考虑底层实现的细节。
好在retrofit提供了Url 参数替换注解@Url String url,通过这个注解我们可以动态的设置请求的url。
下面列出一些简单的参数注解
@Url 替换url@QueryMap 替换url中查询参数@Header 替换header@FieldMap 替换post请求body中参数@FormUrlEncoded post请求需要加的方法注解@POST() 标示该方法为post请求@GET() 标示该方法为get请求
了解了这些注解这样我们就可以将我们项目的请求变成几个基本的方法,由于我的项目的服务端返回的基本格式不是固定的,而GsonConverterFactory,对于retrofit的返回类型要求只能是: 具体对象、jsonObject、jsonArray这三种 ,为了避免每个请求写两个方法,这里我自己写了个返回类型为String的解析器,参考 Retrofit自定义Converter之StringConverterFactory
这样我们的返回类型都是String
public interface RetrofitHttpService { @GET() Call<String> get(@Url String url, @QueryMap Map<String, String> params, @Header("Cache-Time") String time); @FormUrlEncoded @POST() Call<String> post(@Url String url, @FieldMap Map<String, String> params, @Header("Cache-Time") String time);}
如果你项目的返回请求外层有固定的格式可以把 Call<JsonObject>
替换成Call<Model>
,这里的model就是你的基础数据返回类型。
如果你要使用rxjava的话需要额外两个注解方法
@GET() Observable<String> Obget(@Url String url, @QueryMap Map<String, String> params, @Header("Cache-Time") String time); @FormUrlEncoded @POST() Observable<String> Obpost(@Url String url, @FieldMap Map<String, String> params, @Header("Cache-Time") String time);
构建网络数据请求类,这里为了方便不同的项目使用,用一个builder类来构建单例
public class HttpUtil { private static volatile HttpUtil mInstance; private static volatile RetrofitHttpService mService; private Context mAppliactionContext; private static String mVersionApi; private ParamsInterceptor mParamsInterceptor; //构造函数私有,不允许外部调用 private HttpUtil(RetrofitHttpService mService, Context mAppliactionContext, String mVersionApi, ParamsInterceptor mParamsInterceptor) { this.mService = mService; this.mAppliactionContext = mAppliactionContext; this.mVersionApi = mVersionApi; this.mParamsInterceptor = mParamsInterceptor; } public static class SingletonBuilder { private Context appliactionContext; private String baseUrl; private List<String> servers = new ArrayList<>(); private String versionApi; private ParamsInterceptor paramsInterceptor; private List<Converter.Factory> converterFactories = new ArrayList<>(); private List<CallAdapter.Factory> adapterFactories = new ArrayList<>(); OkHttpClient client; public SingletonBuilder(Context context) { try {//防止传入的是activity的上下文 Activity activity = (Activity) context; appliactionContext = context.getApplicationContext(); } catch (Exception e) { e.printStackTrace(); appliactionContext = context; } } public SingletonBuilder client(OkHttpClient client) { this.client = client; return this; } public SingletonBuilder versionApi(String versionApi) { this.versionApi = versionApi; return this; } public SingletonBuilder paramsInterceptor(ParamsInterceptor interceptor) { this.paramsInterceptor = interceptor; return this; } public SingletonBuilder baseUrl(String baseUrl) { this.baseUrl = baseUrl; return this; } public SingletonBuilder addServerUrl(String ipUrl) { this.servers.add(ipUrl); return this; } public SingletonBuilder serverUrls(List<String> servers) { this.servers = servers; return this; } public SingletonBuilder addConverterFactory(Converter.Factory factory) { this.converterFactories.add(factory); return this; } public SingletonBuilder addCallFactory(CallAdapter.Factory factory) { this.adapterFactories.add(factory); return this; } public HttpUtil build() { if (checkNULL(this.baseUrl)) { throw new NullPointerException("BASE_URL can not be null"); } if (converterFactories.size() == 0) { converterFactories.add(StringConverterFactory.create()); } if (adapterFactories.size() == 0) { adapterFactories.add(RxJavaCallAdapterFactory.create()); } if (client == null) { client = OkhttpProvidede.okHttpClient(appliactionContext, baseUrl, servers); } Retrofit.Builder builder = new Retrofit.Builder(); for (Converter.Factory converterFactory : converterFactories) { builder.addConverterFactory(converterFactory); } for (CallAdapter.Factory adapterFactory : adapterFactories) { builder.addCallAdapterFactory(adapterFactory); } Retrofit retrofit = builder .baseUrl(baseUrl + "/") .client(client).build(); RetrofitHttpService retrofitHttpService = retrofit.create(RetrofitHttpService.class); mInstance = new HttpUtil(retrofitHttpService, appliactionContext, versionApi, paramsInterceptor); return mInstance; } }
一般网络请求都是异步的,那么此时我们进行异步调用网络请求的代码是这样的
HttpUtil.getmInstance(mContext).get("url",params,"3600*24").enqueue(new Callback<JsonObject>() { @Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) { } @Override public void onFailure(Call<JsonObject> call, Throwable t) { } });
以上的代码已经采用了回调的方式,保证了onResponse()和 onFailure()里的代码都是在主线程里执行的,这样的代码相对于handler那种已经简洁易用了很多,不过我们不能满足于此,比如判断单例是否实例化并去获取单例的方法根本没必要每次调用都去做,我们只需要在application里初始化就可以了。回调的参数是Call 和Response ,我们肯定需要对他做同样的处理拿出里面的json值才能用的。这样这些代码就可以进一步封装。
retrofit里面提供了异步回调接口类Callback<T>
,不过我们不能直接拿来用,因为一旦我们换网络请求框架。肯定是不能再使用旧的框架里面的回调接口的,所以需要我们定义自己的外层回调接口,一般有成功的回调和失败的回调两种。由于我支持lambda,所以我会把不同的情况分别定义成接口。如何在android中使用lambda请看这篇Androidstudio使用java8、lambda表达式教程
成功回调,一般就是返回的json串,一个参数就够了
@FunctionalInterfacepublic interface Success { void Success( String model);}
失败回调,失败回调不同的网络框架返回的参数个数不一样,这里我们定义成Object数组
@FunctionalInterfacepublic interface Error { void Error(Object... values);}
下面我们封装post请求
public static void post(String url, Map<String, String> params, String cacheTime,Success mSuccessCallBack ,Error mErrorCallBack){ mInstance.post(url, params, cacheTime).enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { if (response.code() == 200) { mSuccessCallBack.Success(response.body().toString()); } else { mErrorCallBack.Error(response.code(), message(response.message()), null); } } @Override public void onFailure(Call<String> call, Throwable t) { mErrorCallBack.Error(200, message(t.getMessage()), t); } });}
此时我们调用post请求时是这样的
HttpUtil.get("url",params,"3600*24", new Success() { @Override public void Success(String model) { } },new Error() { @Override public void Error(Object... value) { } });
独立回调的方式,使用过Volley的人应该熟悉这种方式,这样我们每次调用post的时候只要调用这个方法就可以了,其他几个请求方法一样的封装方式。
但是这样我还是觉得不够简洁,不够优雅,必传参数太多了(哪怕传入null)。两个回调函数看起来也太臃肿了(接口方法增加了代码长度,当然可以用lambda优化,不过那样看起来不伦不类,其实并不利于阅读)。有时候我们是只有一个url的,有时候我们却还会有查询参数的,有时候我们的url是要追加版本号的,有时候我们是需要当前接口支持缓存的,而有的项目是需要统一追加各种配置参数的,如设备号,手机号码等等。这样我们的请求方法的参数个数就是不固定的,比较暴力的方法就是写多个不同参数的重载方法。我以前一般是这么干的,不过太low,这里我们采用builder模式。
public static class Builder { Map<String, String> params = new HashMap<>(); String url; Error mErrorCallBack; Success mSuccessCallBack; String cacheTime; boolean addVersion = false; public Builder CacheTime(String time) { this.cacheTime = time; return this; } public Builder Url(String url) { this.url = url; return this; } public Builder Params(Map<String, String> params) { this.params.putAll(params); return this; } public Builder Params(String key, String value) { this.params.put(key, value); return this; } public Builder Success(Success success) { this.mSuccessCallBack = success; return this; } public Builder Version() { this.addVersion = true; return this; } public Builder Error(Error error) { this.mErrorCallBack = error; return this; } public Builder() { this.setParams(); } public Builder(String url) { this.setParams(url); } private void setParams() { this.setParams(null); } private void setParams(String url) { if (mInstance == null) { throw new NullPointerException("HttpUtil has not be initialized"); } this.url = url; this.params = new HashMap<>(); this.mErrorCallBack = (v) -> { }; this.mSuccessCallBack = (s) -> { }; } private String checkUrl(String url) { if (Util.checkNULL(url)) { throw new NullPointerException("absolute url can not be empty"); } if (addVersion && !url.contains(mVersionApi)) { url = V(url); } return url; } public void get() { this.url = checkUrl(this.url); this.params = checkParams(this.params); if (cacheTime == null) { cacheTime = ""; } mInstance.get(url, checkParams(params), cacheTime).enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { if (response.code() == 200) { mSuccessCallBack.Success(response.body().toString()); } else { mErrorCallBack.Error(response.code(), message(response.message()), null); } } @Override public void onFailure(Call<String> call, Throwable t) { mErrorCallBack.Error(200, message(t.getMessage()), t); } }); }}
checkParams()方法就是对参数的统一处理,追加参数什么的可以在这里面做,Version()方法 是决定要不要给url追加开发版本号。写了这么一大堆,貌似代码变多了啊。别担心,下面我们看看当我们调用请求的时候的代码是多少
new HttpUtil.Builder("favorite_authorized/list?page=1") .Version() .CacheTime("3600*24") .Params("carId", sb.toString()) .Params(sortMap_) .Success((s) -> { ld_.dismiss(); BaseModel model = new BaseModel(s); }) .Error((v) -> { ld_.dismiss(); handler_.obtainMessage(MSG, v[1]).sendToTarget(); }) .get(); });
就这么多,采用链式调用,上面我们动态设置了请求的url,参数,追加开发版本号,追加参数,设置了缓存一天,代码简洁明了,实际使用中我们可以根据单个请求的不同需求决定添加什么方法链。
如果你的项目需要支持缓存,请参照okhttp之自定义Interceptor:缓存拦截器 这篇博客
如果你项目需要失败重试和切换服务器IP并且服务端不支持需要客户端配置实现,请参照 okhttp之自定义Interceptor:请求失败切换IP重试拦截器
下面我们添加取消请求
/**添加某个请求*@author Administrator*@date 2016/10/12 11:00*/ private static synchronized void putCall(Object tag, String url, Call call) { if (tag == null) return; synchronized (CALL_MAP) { CALL_MAP.put(tag.toString() + url, call); } } /* *取消某个界面都所有请求,或者是取消某个tag的所有请求 * 如果要取消某个tag单独请求,tag需要转入tag+url *@author Administrator *@date 2016/10/12 10:57 */ public static synchronized void cancel(Object tag) { if (tag == null) return; List<String> list = new ArrayList<>(); synchronized (CALL_MAP) { for (String key : CALL_MAP.keySet()) { if (key.startsWith(tag.toString())) { CALL_MAP.get(key).cancel(); list.add(key); } } } for (String s : list) { removeCall(s); } } /* *移除某个请求 *@author Administrator *@date 2016/10/12 10:58 */ private static synchronized void removeCall(String url) { synchronized (CALL_MAP) { for (String key : CALL_MAP.keySet()) { if (key.contains(url)) { url = key; break; } } CALL_MAP.remove(url); } }
在请求类builder构建时添加进tag
Object tag; public Builder Tag(Object tag) { this.tag = tag; return this; }
在call构建时将添加进全局静态map,请求返回时移除掉,免得持有引用导致内存泄漏
public void get() { if (cacheTime == null) { cacheTime = ""; } Call call = mInstance.get(checkUrl(this.url), checkParams(params), cacheTime); putCall(tag, url, call);//将call添加进map call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { if (response.code() == 200) { mSuccessCallBack.Success(response.body().toString()); } else { mFailureCallBack.Failure(response.code(), message(response.message()), null); mErrorCallBack.Error(response.code(), message(response.message()), null); } if (tag != null) removeCall(url);//移除call } @Override public void onFailure(Call<String> call, Throwable t) { mFailureCallBack.Failure(200, message(t.getMessage()), t); mErrorCallBack.Error(200, message(t.getMessage()), t); if (tag != null) removeCall(url);//移除call } }); }
下面贴出完整的httputil类
package com.sunshine.retrofit;import android.app.Activity;import android.content.Context;import android.widget.Toast;import com.sunshine.retrofit.converter.StringConverterFactory;import com.sunshine.retrofit.interfaces.Error;import com.sunshine.retrofit.interfaces.ParamsInterceptor;import com.sunshine.retrofit.interfaces.Success;import com.sunshine.retrofit.utils.OkhttpProvidede;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import okhttp3.OkHttpClient;import retrofit2.Call;import retrofit2.CallAdapter;import retrofit2.Callback;import retrofit2.Converter;import retrofit2.Response;import retrofit2.Retrofit;import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;import rx.Observable;import rx.android.schedulers.AndroidSchedulers;import rx.schedulers.Schedulers;/** * Created by 耿 on 2016/6/28. */public class HttpUtil { private static volatile HttpUtil mInstance; private static volatile RetrofitHttpService mService; private Context mAppliactionContext; private static String mVersionApi; private ParamsInterceptor mParamsInterceptor; //构造函数私有,不允许外部调用 private HttpUtil(RetrofitHttpService mService, Context mAppliactionContext, String mVersionApi, ParamsInterceptor mParamsInterceptor) { this.mService = mService; this.mAppliactionContext = mAppliactionContext; this.mVersionApi = mVersionApi; this.mParamsInterceptor = mParamsInterceptor; } public static RetrofitHttpService getService() { if (mInstance == null) { throw new NullPointerException("HttpUtil has not be initialized"); } return mService; } public static class SingletonBuilder { private Context appliactionContext; private String baseUrl; private List<String> servers = new ArrayList<>(); private String versionApi; private ParamsInterceptor paramsInterceptor; private List<Converter.Factory> converterFactories = new ArrayList<>(); private List<CallAdapter.Factory> adapterFactories = new ArrayList<>(); OkHttpClient client; public SingletonBuilder(Context context) { try {//防止传入的是activity的上下文 Activity activity = (Activity) context; appliactionContext = context.getApplicationContext(); } catch (Exception e) { e.printStackTrace(); appliactionContext = context; } } public SingletonBuilder client(OkHttpClient client) { this.client = client; return this; } public SingletonBuilder versionApi(String versionApi) { this.versionApi = versionApi; return this; } public SingletonBuilder paramsInterceptor(ParamsInterceptor interceptor) { this.paramsInterceptor = interceptor; return this; } public SingletonBuilder baseUrl(String baseUrl) { this.baseUrl = baseUrl; return this; } public SingletonBuilder addServerUrl(String ipUrl) { this.servers.add(ipUrl); return this; } public SingletonBuilder serverUrls(List<String> servers) { this.servers = servers; return this; } public SingletonBuilder addConverterFactory(Converter.Factory factory) { this.converterFactories.add(factory); return this; } public SingletonBuilder addCallFactory(CallAdapter.Factory factory) { this.adapterFactories.add(factory); return this; } public HttpUtil build() { if (checkNULL(this.baseUrl)) { throw new NullPointerException("BASE_URL can not be null"); } if (converterFactories.size() == 0) { converterFactories.add(StringConverterFactory.create()); } if (adapterFactories.size() == 0) { adapterFactories.add(RxJavaCallAdapterFactory.create()); } if (client == null) { client = OkhttpProvidede.okHttpClient(appliactionContext, baseUrl, servers); } Retrofit.Builder builder = new Retrofit.Builder(); for (Converter.Factory converterFactory : converterFactories) { builder.addConverterFactory(converterFactory); } for (CallAdapter.Factory adapterFactory : adapterFactories) { builder.addCallAdapterFactory(adapterFactory); } Retrofit retrofit = builder .baseUrl(baseUrl + "/") .client(client).build(); RetrofitHttpService retrofitHttpService = retrofit.create(RetrofitHttpService.class); mInstance = new HttpUtil(retrofitHttpService, appliactionContext, versionApi, paramsInterceptor); return mInstance; } } public static String V(String url) { if (checkNULL(mVersionApi)) { throw new NullPointerException("can not add VersionApi ,because of VersionApi is null"); } if (!url.contains(mVersionApi)) { return mVersionApi + url; } return url; } public static Map<String, String> checkParams(Map<String, String> params) { if (params == null) { params = new HashMap<>(); } if (mInstance.mParamsInterceptor != null) { params = mInstance.mParamsInterceptor.checkParams(params); } //retrofit的params的值不能为null,此处做下校验,防止出错 for (Map.Entry<String, String> entry : params.entrySet()) { if (entry.getValue() == null) { params.put(entry.getKey(), ""); } } return params; } // 判断是否NULL public static boolean checkNULL(String str) { return str == null || "null".equals(str) || "".equals(str); } // 判断是否NULL public static void Error(Context context, String msg) { if (checkNULL(msg)) { msg = "似乎已断开与互联网连接"; } Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); } public static String message(String mes) { if (checkNULL(mes)) { mes = "似乎已断开与互联网连接"; } if (mes.equals("timeout") || mes.equals("SSL handshake timed out")) { return "网络请求超时"; } else { return mes; } } static Map<String, Call> CALL_MAP = new HashMap<>(); /* *添加某个请求 *@author Administrator *@date 2016/10/12 11:00 */ private static synchronized void putCall(Object tag, String url, Call call) { if (tag == null) return; synchronized (CALL_MAP) { CALL_MAP.put(tag.toString() + url, call); } } /* *取消某个界面都所有请求,或者是取消某个tag的所有请求 * 如果要取消某个tag单独请求,tag需要转入tag+url *@author Administrator *@date 2016/10/12 10:57 */ public static synchronized void cancel(Object tag) { if (tag == null) return; List<String> list = new ArrayList<>(); synchronized (CALL_MAP) { for (String key : CALL_MAP.keySet()) { if (key.startsWith(tag.toString())) { CALL_MAP.get(key).cancel(); list.add(key); } } } for (String s : list) { removeCall(s); } } /* *移除某个请求 *@author Administrator *@date 2016/10/12 10:58 */ private static synchronized void removeCall(String url) { synchronized (CALL_MAP) { for (String key : CALL_MAP.keySet()) { if (key.contains(url)) { url = key; break; } } CALL_MAP.remove(url); } } public static class Builder { Map<String, String> params = new HashMap<>(); String url; Error mErrorCallBack; Success mSuccessCallBack; String cacheTime; boolean addVersion = false; Object tag; public Builder CacheTime(String time) { this.cacheTime = time; return this; } public Builder Url(String url) { this.url = url; return this; } public Builder Tag(Object tag) { this.tag = tag; return this; } public Builder Params(Map<String, String> params) { this.params.putAll(params); return this; } public Builder Params(String key, String value) { this.params.put(key, value); return this; } public Builder Success(Success success) { this.mSuccessCallBack = success; return this; } public Builder Version() { this.addVersion = true; return this; } public Builder Error(Error error) { this.mErrorCallBack = error; return this; } public Builder() { this.setParams(); } public Builder(String url) { this.setParams(url); } private void setParams() { this.setParams(null); } private void setParams(String url) { if (mInstance == null) { throw new NullPointerException("HttpUtil has not be initialized"); } this.url = url; this.params = new HashMap<>(); this.mErrorCallBack = (v) -> { }; this.mSuccessCallBack = (s) -> { }; } private String checkUrl(String url) { if (checkNULL(url)) { throw new NullPointerException("absolute url can not be empty"); } if (addVersion) { url = mInstance.V(url); } return url; } public void get() { if (cacheTime == null) { cacheTime = ""; } Call call = mService.get(checkUrl(this.url), checkParams(params), cacheTime); putCall(tag, url, call); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { if (response.code() == 200) { mSuccessCallBack.Success(response.body().toString()); } else { mErrorCallBack.Error(response.code(), message(response.message()), null); } if (tag != null) removeCall(url); } @Override public void onFailure(Call<String> call, Throwable t) { mErrorCallBack.Error(200, message(t.getMessage()), t); if (tag != null) removeCall(url); } }); } public void post() { if (cacheTime == null) { cacheTime = ""; } Call call = mService.post(checkUrl(this.url), checkParams(params), cacheTime); putCall(tag, url, call); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { if (response.code() == 200) { mSuccessCallBack.Success(response.body().toString()); } else { mErrorCallBack.Error(response.code(), message(response.message()), null); } if (tag != null) removeCall(url); } @Override public void onFailure(Call<String> call, Throwable t) { mErrorCallBack.Error(200, message(t.getMessage()), t); if (tag != null) removeCall(url); } }); } public Observable<String> Obget() { this.url = checkUrl(this.url); this.params = checkParams(this.params); if (cacheTime == null) { cacheTime = ""; } return mService.Obget(url, checkParams(params), cacheTime); } public Observable<String> Obpost() { this.url = checkUrl(this.url); this.params = checkParams(this.params); if (cacheTime == null) { cacheTime = ""; } return mService.Obpost(url, checkParams(params), cacheTime); } /* *按基础格式返回的数据进行预处理 *只返回status为true的情况下的data *@author Administrator *@date 2016/10/20 11:31 */ public Observable<String> getModelData(Context context) { return Obget() .map(s -> new BaseModel(s)) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .filter(model -> model.trueStatus(context))//可能有toast操作,必须在主线程 .map(model -> model.data); } public Observable<String> postModelData(Context context) { return Obpost() .map(s -> new BaseModel(s)) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .filter(model -> model.trueStatus(context)) .map(model -> model.data); } }}
以上就是本次retrofit的封装的完整实现了
完整的示例项目地址https://github.com/gengqiquan/HttpUtil.git
有什么建议的可以留言喔
如果我的博客对您有帮助,请留言鼓励下或者点个赞吧!
我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。
- 浅谈Retrofit封装-让框架更加简洁易用
- 浅谈Android网络封装框架Retrofit
- AndroidAnnotations一个可以让你的android代码更加简洁的框架
- AndroidAnnotations一个可以让你的android代码更加简洁的框架
- 让java代码更加的简洁
- Retrofit框架基本封装
- Retrofit+Rxjava网络封装框架
- Reeder for Chrome:让 Google Reader 更加简洁美观
- 让Activity更加简洁第一篇---MVP模式
- 让Activity更加简洁第二篇---AsyncTask的使用姿势
- 使用MVP+Retrofit+rxjava让你的代码更简洁
- 重新封装BaseAdapter,打造最简洁框架
- 更加简洁易用——wangEditor富文本编辑器新版本发布
- Retrofit+OKhttp+RxJava框架的封装
- Retrofit网络框架的封装使用
- 封装Retrofit + okhttp + rxjava网络请求框架
- Afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框架,使其更加简单易用
- recyclerview_helper多功能封装,让你应用更加自如
- leetcode_c++:树:Count Complete Tree Nodes(222 )
- JDK安装与环境变量配置
- 11 第一个特效 12灯泡开关案列 13 找对象 14操作对象
- java 发送邮件
- 用实例来理解IComparable和IComparer
- 浅谈Retrofit封装-让框架更加简洁易用
- JPA 多对多关联查询
- LintCode(easy)不同的路径
- 项目进展
- web.xml中【url-pattern的配置】
- Java 实现复制文本文件的两种方法
- HTTP1.0,1.1与2.0
- 开发app在android6.0运行直接退出解决(二)
- 如何获取数据库表的主键值?