想不想让网络请求变得可控?想不想让网络请求变得更加简单?有句话说得好,不会偷懒的程序员就不是一个好程序员。那如何偷懒呢?以retrofit网络请求为例,对retrofit网络请求进行自定义ConverterFactory封装使用。不足之处,请大佬不吝赐教。
1、Retrofit介绍
Retrofit是对网络请求框架的封装。需要说明的是Retrofit不是网络请求框架,是因为Retrofit的网络请求是交给OkHttp完成的。Retrofit只专注于对请求接口的封装。Retrofit的出现是网络请求接口定义与使用分离开来,是代码更加简练,同时灵活的http client配置以及支持多种返回数据解析的Converter配置可以快速进行数据转换等功能,是项目中的网络请求变得更加简单。
2、Retrofit使用
Retrofit使用网上已经有很多的案例,这里我不做深入分析,在这里我简单介绍一下retrofit的使用。
a) 创建OkHttpClient对象
client = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
//添加日志打印拦截器
.addInterceptor(new LoggerInterceptor(Constant.LOGISHOW))
.addInterceptor(new TokenInterceptor())
.retryOnConnectionFailure(true)
.build();
b) 创建Retrofit对象
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
c) 定义Service接口
public interface ApiService {
@GET("weather_mini")
Call<Login> requesntLoat(@QueryMap HashMap<String,String>params);
}
d)获取Call对象,并执行请求,获取网络数据
ApiService mService= ApiRetroift.build().create(ApiService.class);
Call<Login> call = mService.requesntLoat(params);
call.enqueue(new Callback<Login>() {
@Override
public void onResponse(Call<Login> call, Response<Login> response) {
}
@Override
public void onFailure(Call<Login> call, Throwable t) {
}
});
上面是对retrofit的简单实用,如果项目中功能不多,网络请求也不很负责情况下,这样写已经完全满足需求了。但我们实际项目开发中,一般会用到几十甚至上千个网络请求,如果对每个网络请求都单独处理,势必会增加我们很多工作量。我们需要对这些网络请求统一处理,对网络数据和可能的异常统一拦截处理。下面我们通过自定义ConverterFactory对网络实现统一异常处理。
3、Retrofit 自定义ConverterFactory
a) 创建适配器工厂
创建ApiCallAdapterFactory类并继承CallAdapter.Factory,作为Retrofit返回的新工厂。这里继承CallAdapter.Factory类,需要重写Factory的get方法,而get方法的返回对象决定了你将采取什么样的CallAdapter对象。
public class ApiCallAdapterFactory extends CallAdapter.Factory {
@Nullable
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return null;
}
}
下面是对get方法的重写
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class && getRawType(returnType) != Observable.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
if (getRawType(responseType) == Call.class){
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new DefaultExecutorCallbackCall<>(executor, call);
}
};
}else{
return new ApiCallAdapter<>(responseType,executor);
}
}
这里为了不破坏定义Service返回的原有的Call对象,这里我只做了增量返回。就是监测方法的返回值类型如果是Call.class,则我们继续返回Retrofit默认的 DefaultExecutorCallbackCall对象,如果是我们自己申明的Observable.class,则返回我们自定义的ApiCallAdapter对象。
b) 定义Observable接口,作为Service中方法的返回类型
public interface Observable<R>{
/*取消请求*/
void cancel();
/*关联监听对象,并发起请求*/
void subscribeWith(ApiObserver<R> observe);
/*关联监听时间*/
void detection(Disposable disposable);
/*判断是否已执行*/
boolean isExecuted();
/*克隆当前请求对象 clone*/
Observable<R> clone();
/** The original HTTP request. */
Request request();
/*timeout*/
Timeout timeout();
}
c)创建EnqueueObservable类,并实现Observable<R>接口
public class EnqueueObservable<R> implements Observable<R> {
private final Call<R> call;
private final Executor callbackExecutor;
private Disposable mDisposable;
public EnqueueObservable(Call<R> call, Executor callbackExecutor) {
this.call = call;
this.callbackExecutor = callbackExecutor;
}
...
}
其中在重写的subscribeWith中,完成对网络请求的发起和对请求返回的数据及可能的异常统一处理
@Override
public synchronized void subscribeWith(ApiObserver<R> observe) {
Objects.requireNonNull(observe, "observe == null");
observe.onStart();
call.enqueue(new Callback<R>() {
@Override
public void onResponse(Call<R> call, final Response<R> response) {
if (call.isCanceled()) {
observe.onFailure(new ApiException(-1,"Canceled"));
} else {
int code = response.code();
if (200<=code && code <=299){
observe.onNext(response.body());
}else{
observe.onFailure(new ApiException(code,response.message()));
}
}
observe.onFinish();
}
@Override
public void onFailure(Call<R> call, final Throwable t) {
observe.onFailure(ExceptionHelper.transformException(t));
observe.onFinish();
}
});
}
其中ApiException是我们定义网络请求异常类
public class ApiException {
private int code;
private String message;
public ApiException(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
ApiObserver是用来监听网络请求的回调类
public interface ApiObserver<R>{
void onStart();
void onNext(R data);
void onFailure(ApiException t);
void onFinish();
}
4、使用自定义的ApiCallAdapterFactory工厂
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory( ApiCallAdapterFactory.create())
.build();
a) 自定义Observable接口的使用
public interface ApiService {
@GET("weather_mini")
Observable<Login> requesntLoat(@QueryMap HashMap<String,String>params);
}
5、创建NetDisposable类,对网络请求进行统一管理
NetDisposable类是为了统一管理网络请求,防止页面销毁网络请求还在继续执行的问题。当Activity或者Fragment销毁的时候,在onDestory会调用中触发NetDisposable的disposeAll方法,取消所有网路请求。
public class NetDisposable {
LinkedList<Observable>mObservables;
public void dispose() {
for (int i = 0; i < mObservables.size(); i++) {
Observable ob = mObservables.get(i);
if (ob.isExecuted()){
mObservables.remove(ob);
i--;
}
}
}
public void add(Observable observable){
if (null == mObservables){
mObservables = new LinkedList<>();
}
observable.detection(new Disposable() {
@Override
public void dispose() {
NetDisposable.this.dispose();
}
});
mObservables.add(observable);
}
public void disposeAll(){
for (Observable ob:mObservables) {
ob.cancel();
}
mObservables.clear();
}
}
6、结合MVP模式,创建ApiPresenter类,并在ApiPresenter中统一发送请求,让请求变得更简单。使用是只需要让我们的BasePresenter类继承ApiPresenter
public class ApiPresenter {
private NetDisposable mDisposable;
/*接触绑定,同时取消网络请求*/
public void deteachView() {
removeDispose();
}
public <T> void sendRequest(Observable<T> observable, ResultBack observer) {
if (null == mDisposable){
mDisposable = new NetDisposable();
}
mDisposable.add(observable);
observable.subscribeWith(observer);
}
private void removeDispose() {
if (null != mDisposable ) {
mDisposable.disposeAll();
}
}
}
7、创建ResultBack类,让回调变得更简单
public abstract class ResultBack<T> implements ApiObserver<T> {
private final String TAG = "Api";
Context context;
public ResultBack(Context context){
this.context = context;
}
@Override
public void onStart() {
//请求开始
}
@Override
public void onNext(T data) {
//接收到数据
onSuccess(data);
}
@Override
public void onFailure(ApiException t) {
Log.i(TAG,"=========================="+ t.getMessage());
onFaild(t.getCode(),t.getMessage());
}
@Override
public void onFinish() {
//请求结束
}
public abstract void onSuccess(T data);
public abstract void onFaild(int code,String message);
}
8、在MVP的P层中发起请求
public void requestLogin(Context context){
HashMap<String,String>params = new HashMap<>();
params.put("city","沈阳");
sendRequest(mService.requesntLoat(params),new ResultBack<Login>(context){
@Override
public void onSuccess(Login data) {
Log.d("API", "onSuccess: ======="+data.toString());
}
@Override
public void onFaild(int code, String message) {
}
});
}