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;
}