Retrofit自定义CallAdapterFactory

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>
   * &#64;Override
   * public &lt;R&gt; Async&lt;R&gt; adapt(final Call&lt;R&gt; call) {
   *   return Async.create(new Callable&lt;Response&lt;R&gt;&gt;() {
   *     &#64;Override
   *     public Response&lt;R&gt; 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;
    }

猜你喜欢

转载自blog.csdn.net/suyimin2010/article/details/80197112