retrofit自从面世,一直很火,现在大多android开发的都在用的网络框架。我们在设置retrofit的时候需要设置CallAdapterFactory
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.stonebangbang.com/test.php/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.creat()) .build(); return retrofit.create(apiServiceClass);这是用rxjava自定义的adapter来实现的,我们一般都是这么用,但是如果我们要自定义calladapter的时候该怎么做呢?
现在我们来看看calladapter是干什么的
abstract class Factory { /** * Returns a call adapter for interface methods that return {@code returnType}, or null if it * cannot be handled by this factory. */ public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); /** * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For * example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}. */ protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } /** * Extract the raw class type from {@code type}. For example, the type representing * {@code List<? extends Runnable>} returns {@code List.class}. */ protected static Class<?> getRawType(Type type) { return Utils.getRawType(type); } }这是一个抽象类,我们需要实现get方法,先来看看这几个方法都是干嘛的。
getParameterUpperBound
首先getParameterUpperBound方法,他是获取参数的type的,我觉得可以把它理解为获取的泛型,比如我们写了个User<T>,
我们可以new User<Man>这个man就是我们实例化的type。在看这个方法,他有两个参数,一个是index,是指位置,比如我们的User<T,V> 这个T就是0,这个V就是1,parameterizedType是个接口,继承type接口,从字面上来看是参数类型,所以我把它理解为我们定义的这个T的类型,比如man,比如我们传入的任何实例,如果我们没有传入那就不是parameterizedtype类型的。
而getRawType是提取的实例class,如果我们的User<T> 他得到的就是User.class。
而get方法是返回一个calladapter,所以我们要顶一个calladatper,再来看下calladapter,
public interface CallAdapter<R, T> { /** * Returns the value type that this adapter uses when converting the HTTP response body to a Java * object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type * is used to prepare the {@code call} passed to {@code #adapt}. * <p> * Note: This is typically not the same type as the {@code returnType} provided to this call * adapter's factory. */ Type responseType(); /** * Returns an instance of {@code T} which delegates to {@code call}. * <p> * For example, given an instance for a hypothetical utility, {@code Async}, this instance would * return a new {@code Async<R>} which invoked {@code call} when run. * <pre><code> * @Override * public <R> Async<R> adapt(final Call<R> call) { * return Async.create(new Callable<Response<R>>() { * @Override * public Response<R> call() throws Exception { * return call.execute(); * } * }); * } * </code></pre> */ T adapt(Call<R> call);
它是个接口,有两个方法,一个是responseType,这个就是从网络获取数据response的类型,也就是我们gson活着fastjson需要解析用到的那个type,这个很重要,如果这个传错了,那我们用gson解析json成model的时候就会报错。
adapt就是返回的实例,类似于我们写service的那个observable.
好了基本内容介绍完了,现在写个实例吧,retrofit adapter已经写了一个实例,大家可以做参考,不过我们自己实现的话,其实不用那么复杂。
public class LiveDataCallAdapterFactory extends CallAdapter.Factory { @Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != LiveData.class) { return null; } Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType); Class<?> rawObservableType = getRawType(observableType); Timber.d("rawObservableType = " + rawObservableType.getSimpleName()); if (rawObservableType != ResponseData.class) { throw new IllegalArgumentException("type must be a resource"); } if (! (observableType instanceof ParameterizedType)) { throw new IllegalArgumentException("resource must be parameterized"); } Type bodyType = getParameterUpperBound(0, (ParameterizedType) observableType); Timber.d("bodyType = " + bodyType.toString()); return new LiveDataCallAdapter<>(observableType); } }这是我对livedata实现的factory,很简单,getRawType和getParameterUpperBound方法已经在上面说过了, 特别需要注意的是,return livedatacalladapter里面传入的type
observableType 是你写的service返回值里面的T,比如LiveData<Response<User>> 他代表的事这个Response<User>
bodyType 代表的事User,当然如果你不关心body的type这块可以忽略。
在看一下LiveDataCallAdapter的写法
public class LiveDataCallAdapter<R> implements CallAdapter<R, LiveData<ResponseData>> { private final Type responseType; public LiveDataCallAdapter(Type responseType) { this.responseType = responseType; } @Override public Type responseType() { return responseType; } @Override public LiveData<ResponseData> adapt(Call<R> call) { return new LiveData<ResponseData>() { AtomicBoolean started = new AtomicBoolean(false); @Override protected void onActive() { super.onActive(); if (started.compareAndSet(false, true)) { call.enqueue(new Callback<R>() { @Override public void onResponse(Call<R> call, Response<R> response) { Timber.d("success"); ResponseData responseData = new ResponseData<>(); if(response.isSuccessful()){ responseData = (ResponseData) response.body(); }else{ try { responseData.setMessage(response.errorBody().string()); } catch (IOException e) { e.printStackTrace(); } responseData.setData(null); responseData.setCode(response.code()); } postValue(responseData); } @Override public void onFailure(Call<R> call, Throwable throwable) { ResponseData responseData = new ResponseData<>(); responseData.setCode(500); responseData.setData(null); responseData.setMessage(throwable.getMessage()); Timber.d(throwable," failure"); postValue(responseData); } }); } } }; } }responseType 就是刚才在factory里面传进来的,gson在解析的时候会用到这个type。
adpt非常简单,rxjava的事返回的object,更灵活一些,我们自己定义的话这块完全可以写死,想要response是什么这块就返回什么就可以了。我所以得网络请求返回的都是livedata<ResponseData> 所以这块我就直接写死了。Call是retrofit自带的。
responseData是我自己定义的一个类。
public class ResponseData<T> implements Serializable { protected boolean success; protected int code; protected String message; protected T date; public boolean isSuccess() { return true; } public void setSuccess(boolean success) { this.success = success; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public T getData() { return date; } public void setData(T data) { this.date = data; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }