码迷,mamicode.com
首页 > 其他好文 > 详细

Retrofit的使用与深入学习(下)

时间:2016-05-06 15:14:42      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:


注意:以下分析都是基于Retrofit2

    本节是《Retrofit的使用与深入学习》的进阶版本,着重讲解一下Retrofit中的Converter.Factory和CallAdapter.Factory两个对象。正式介绍之前,首先回顾一下这两个抽象类都定义了哪些方法:
public interface CallAdapter<T> {
  Type responseType();   //该请求适配器返回的数据类型
  <R> T adapt(Call<R> call);  //该请求适配器对原始Call的再次封装,如Call<R>到Observable<R>,这里的Call<R>在retrofit2中都是OkHttpCall对象
  abstract class Factory {
    public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); //获取网络请求适配器
    protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } 
    //Example:完成Map<String, ? extends Runnable> 到  Runnable的转变;第i个参数的最上层的数据类型
    protected static Class<?> getRawType(Type type) {  return Utils.getRawType(type); }
     //Example:完成List<? extends Runnable> 到 List.class的转变;  即得到最外层的那个数据类型
  }
}

public interface Converter<F, T> {
  T convert(F value) throws IOException;
  abstract class Factory {
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } //对响应数据的转换
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null; } //对请求数据的转换
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {  return null;  }  //String类型转换
  }
}
    本节我们将先对Retrofit默认网络请求适配器ExecutorCallAdapterFactoryRxJavaCallAdapterFactory进行介绍,随后介绍Retrofit的默认内容转换器BuiltInConvertersGsonConverterFactory。在此需要在此强调的是Retrofit的ArrayList<CallAdapter.Factory> adapterFactories集合中ExecutorCallAdapterFactory位于该集合的末尾。Retrofit的ArrayList<Converter.Factory> converterFactories集合中BuiltInConverters位于该集合的首位。在接口方法Method向ServiceMethod的转化过程中,都是从adapterFactories和converterFactories集合的首位开始往后找的,因此集合中的工厂位置越靠前就拥有越高的使用权限因为GsonConverterFactory它能对任何数据都可以进行转换(最多转换异常嘛),因此Retrofit作者特别强调一定将GsonConverterFactory添加到Retrofit的converterFactories集合的末尾。

ExecutorCallAdapterFactory.class

final class ExecutorCallAdapterFactory extends CallAdapter.Factory
ExecutorCallAdapterFactory()@ExecutorCallAdapterFactory.class
类只有一个域,即回调方法执行器
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
}
只有一个用于返回CallAdapter<Call<?>>对象的get方法
get()@ExecutorCallAdapterFactory.class
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {  return null; } 
    final Type responseType = Utils.getCallResponseType(returnType);
    
    return new CallAdapter<Call<?>>() {
      @Override public Type responseType() { return responseType; } 
      @Override public <R> Call<R> adapt(Call<R> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } //note1
    };
  }
1、创建一个回调请求执行器,该执行器实现了Call<T>接口
static final class ExecutorCallbackCall<T> implements Call<T>
ExecutorCallbackCall.class@ExecutorCallAdapterFactory.class
final Executor callbackExecutor; //回调方法执行器
final Call<T> delegate;//网络请求实体
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
}
@Override public boolean isExecuted() { return delegate.isExecuted(); }
@Override public Call<T> clone() {  return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); }
@Override public Request request() { return delegate.request(); }

@Override public Response<T> execute() throws IOException {  return delegate.execute(); } //note1
@Override public void enqueue(final Callback<T> callback) {//note2
      if (callback == null) throw new NullPointerException("callback == null");
      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() { 
            @Override public void run() {
              if (delegate.isCanceled()) {  callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } 
              else {  callback.onResponse(ExecutorCallbackCall.this, response); } 
            }
          });
        }
        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {  callback.onFailure(ExecutorCallbackCall.this, t); } 
          });
        }
      });
}
1、同步请求直接调用OkHttpCall的同名方法去执行
2、异步请求将相应的结果交给callbackExecutor回调执行器去执行
    综上我们对ExecutorCallAdapterFactory.class的总结就是,该对象存储一个回调执行器;通过该工厂的get方法得到的CallAdapter对象类型是固定的,跟returnType,annotations等参数都没有关系。CallAdapter对象的adapt方法返回的Call<T>对象基本透明,网络请求都是通过调用adapt传入参数Call<T>对象的同名方法。

RxJavaCallAdapterFactory.class

public final class RxJavaCallAdapterFactory extends CallAdapter.Factory
RxJavaCallAdapterFactory()@RxJavaCallAdapterFactory.class
private final Scheduler scheduler;
private RxJavaCallAdapterFactory(Scheduler scheduler) {
    this.scheduler = scheduler;
}
public static RxJavaCallAdapterFactory create() {
    return new RxJavaCallAdapterFactory(null);
}
scheduler默认是一个null,用于设计Observable.subscribeOn(scheduler);即Subscriber对象的onStart方法执行线程,一般没什么卵用。
get()@RxJavaCallAdapterFactory.class
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType); //note1
    String canonicalName = rawType.getCanonicalName(); //note2
    boolean isSingle = "rx.Single".equals(canonicalName); //note3
    boolean isCompletable = "rx.Completable".equals(canonicalName);
    if (rawType != Observable.class && !isSingle && !isCompletable) { //note4
      return null;
    }
    if (!isCompletable && !(returnType instanceof ParameterizedType)) {
      String name = isSingle ? "Single" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized" + " as " + name + "<Foo> or " + name + "<? extends Foo>"); 
    }
    if (isCompletable) {  
      return CompletableHelper.createCallAdapter(scheduler);
    }
    CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler); //note5
    if (isSingle) {
      return SingleHelper.makeSingle(callAdapter);
    }
    return callAdapter;
}
1、获取返回值类型的最外层的类;对于List<? extends Runnable>就会得到List.class;
2、返回该类含包名的名字;参考
3、是否是rx.Single 、rx.Completable两个类
4、如果返回值类型最外层不是rx.Single 、rx.Completable、Observable则该RxJavaCallAdapterFactory不对其进行处理;将交给Retrofit的adapterFactories集合中的下一个CallAdapter.Factory进行处理。
5、对于Completable<?> Single<?> Observable<?>我们只介绍最后一个Observable<?>

getCallAdapter()@RxJavaCallAdapterFactory.class
private CallAdapter<Observable<?>> getCallAdapter(Type returnType, Scheduler scheduler) {
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType); //note1
    Class<?> rawObservableType = getRawType(observableType); //note2
    if (rawObservableType == Response.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Response must be parameterized"  + " as Response<Foo> or Response<? extends Foo>"); 
      }
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType); //note3
      return new ResponseCallAdapter(responseType, scheduler); //note4
    }
    if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"  + " as Result<Foo> or Result<? extends Foo>"); 
      }
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResultCallAdapter(responseType, scheduler); //note5
    }
    return new SimpleCallAdapter(observableType, scheduler); //note6
  }
1、Observable<Response<T>> 到Response<T>的转变;
2、Response<T> 到 Response的转变;
3、Response<T> 到 T 的转变;
4、Observable<Response<? extends T>>创建一个ResponseCallAdapter对象
5、Observable<Result<? extends T>>创建一个ResultCallAdapter对象
6、默认创建一个SimpleCallAdapter对象,先对该对象进行介绍
SimpleCallAdapter.class@RxJavaCallAdapterFactory.class
static final class SimpleCallAdapter implements CallAdapter<Observable<?>> {
    private final Type responseType;
    private final Scheduler scheduler;
    SimpleCallAdapter(Type responseType, Scheduler scheduler) {
      this.responseType = responseType;
      this.scheduler = scheduler;
    }
    @Override public Type responseType() {
      return responseType;
    }
    @Override public <R> Observable<R> adapt(Call<R> call) {
      Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) // note1
          .lift(OperatorMapResponseToBodyOrError.<R>instance()); //note2
      if (scheduler != null) {
        return observable.subscribeOn(scheduler); //note3
      }
      return observable;
    }
}
哈哈哈,很熟悉的RxJava操作——lift&Operator,如果看到这里你没有眼前一亮或者不懂博主的自言自语,那么十分推荐去看看本人的另外一篇博客RxJava的使用与深入学习,因为接下来的讲解都是默认你知道RxJava的内部工作原理进行讲解的,不然你也可以硬着头皮往下看。
1、CallOnSubscribe<>(Call<R> call)一猜就知道在OnSubscribe的call方法中会利用参数call获取一个最原始的网络Response<R>数据,不信你看CallOnSubscribe.class的call方法源码 (后面有给出);
2、OperatorMapResponseToBodyOrError是对Subscribe对象的一次封装,封装后的Subscribe对象会对前面得到的Response<R>进行一定的预处理后(从Operator的名字来看就是对Response<R>状态进行判断),再传递给后面的Subscribe对象进行处理;
3、如果scheduler不为空则用该scheduler设置Observable的subscribe方法的执行线程

CallOnSubscribe.class@RxJavaCallAdapterFactory.class
static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
    private final Call<T> originalCall; //note1
    CallOnSubscribe(Call<T> originalCall) {
      this.originalCall = originalCall;
    }
    @Override public void call(final Subscriber<? super Response<T>> subscriber) { //note1.5
      Call<T> call = originalCall.clone();
      RequestArbiter<T> requestArbiter = new RequestArbiter<>(call, subscriber); //note2
      subscriber.add(requestArbiter);
      subscriber.setProducer(requestArbiter); //note3
    }
}
1、构造该方法是传入的OkHttpCall对象,用于执行网络请求
1.5、该SubscribeOn能处理的Subscribe对象是Subscriber<? super Response<T>> 类型
2、利用OkHttpCall和Subscriber<? super Response<T>>创建一个事件生成对象
3、一般该方法的结果就是调用requestArbiter.request(Integer.MAX_VALUE);所以我们接下来看看RequestArbiter类的request方法是如何定义的。

RequestArbiter.class@RxJavaCallAdapterFactory.class
static final class RequestArbiter<T> extends AtomicBoolean implements Subscription, Producer {
    private final Call<T> call; //构造该对象时传入的OkHttpCall
    private final Subscriber<? super Response<T>> subscriber; //构造该对象时传入的Subscriber<? super Response<T>>
    RequestArbiter(Call<T> call, Subscriber<? super Response<T>> subscriber) {
      this.call = call;
      this.subscriber = subscriber;
    }
    @Override public void request(long n) {
      if (n < 0) throw new IllegalArgumentException("n < 0: " + n);
      if (n == 0) return; // Nothing to do when requesting 0.
      if (!compareAndSet(false, true)) return; // Request was already triggered.
      try {
        Response<T> response = call.execute(); //note1
        if (!subscriber.isUnsubscribed()) { subscriber.onNext(response); }  //note2
      } catch (Throwable t) {
        Exceptions.throwIfFatal(t);
        if (!subscriber.isUnsubscribed()) { subscriber.onError(t);}  //note3
        return;
      }
       if (!subscriber.isUnsubscribed()) { subscriber.onCompleted(); }  //note4
    }
    @Override public void unsubscribe() {  call.cancel(); }  //note5
    @Override public boolean isUnsubscribed() {   return call.isCanceled(); }  //note6
}
1、通过OkHttpCall的execute——同步请求,获取Response<T>对象
2、如果当前subscribe没有解绑,调用Subscriber<? super Response<T>>的onNext方法处理上面得到的Response<T>对象
3、如果当前subscribe没有解绑,调用Subscriber<? super Response<T>>的onError方法处理异常t
4、如果当前subscribe没有解绑,调用Subscriber<? super Response<T>>的onCompleted()方法
5、如果当前subscribe要求解绑,调用OkHttpCall的cancel()方法断开连接
6、判断一个subscribe是否解绑,实则是判断OkHttpCall是否断开连接
发现没,如果使用Observable<T>进行网络访问,那么一旦Subscribe解除绑定就会断开网络连接,而且不再接收任何网络信息,这也是为什么Retrofit作者建议在Activity和Fragment中使用Retrofit+RxJava时一定要在onDestiny方法中调用subscription.unsubscribe()方法解除绑定的原因,即断开网络连接,回收网络资源。

到此为止我们分析完了SimpleCallAdapter.class@RxJavaCallAdapterFactory.class的note1,得到的Observable<R> 能接收Subscriber<? super Response<T>>类型的订阅者。接着我们继续分析note2的.lift(OperatorMapResponseToBodyOrError.<R>instance())操作。


OperatorMapResponseToBodyOrError.class

final class OperatorMapResponseToBodyOrError<T> implements Operator<T, Response<T>> {
  private static final OperatorMapResponseToBodyOrError<Object> INSTANCE =  new OperatorMapResponseToBodyOrError<>(); 
  static <R> OperatorMapResponseToBodyOrError<R> instance() {
    return (OperatorMapResponseToBodyOrError<R>) INSTANCE;
  }
  @Override public Subscriber<? super Response<T>> call(final Subscriber<? super T> child) {//note1
    return new Subscriber<Response<T>>(child) {
      @Override public void onNext(Response<T> response) { 
        if (response.isSuccessful()) {
          child.onNext(response.body()); //note2
        } else {
          child.onError(new HttpException(response)); //note3
        }
      }
      @Override public void onCompleted() {
        child.onCompleted();
      }
      @Override public void onError(Throwable e) {
        child.onError(e);
      }
    };
  }
}
1、final Subscriber<? super T> child为被包装的Subscribe;call方法返回一个Subscriber<Response<T>>对象;被包装的Subscribe (child) 对象接收T类型数据,包装的Subscribe接收Response<T>类型数据;包装的Subscribe对象的onCompleted和onError方法内部实现就是直接调用被包装Subscribe (child) 对象的onCompleted和onError方法;包装的Subscribe对象的onNext方法稍微复杂点,我们往下看
2、如果Response<T>.isSuccessful()为真,则直接调用child.onNext(response.body()); 即让被包装Subscribe (child) 对象的onNext方法处理response.body()内容。
3、如果Response<T>.isSuccessful()为假,则直接调用child.onError(new HttpException(response));  即让被包装Subscribe child的onNext方法处理new HttpException(response);这也是为什么介绍Retrofit和RxJava配合使用的时候有如下的代码(Line10):
String username = "sarahjean";
Observable<User> call = apiService.getUser(username);
Subscription subscription = call
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<User>() {
   ......
  @Override  public void onError(Throwable e) { 
    if (e instanceof HttpException) {
       HttpException response = (HttpException)e; //Line10
       int code = response.code();
    }
  }
});
不过你发现没,Subscribe只能接受到T类型的数据,即Response.body(),这样我们无法获取到Response<T>的Header部分的数据, 如网络请求的cookie等数据!!!!如果我们一定要获取cookie呢??答案肯定在我们之前漏掉的内容中。。。。回头看看,OperatorMapResponseToBodyOrError操作之前Subscribe接收的数据还是Response<T>,只是OperatorMapResponseToBodyOrError操作后将Response<T>的body取出,传给下一级Subscribe。顺着这个思路,在getCallAdapter()@RxJavaCallAdapterFactory.class中我们只对SimpleCallAdapter进行了介绍,还有两个CallAdapter没有介绍,它们分别是ResponseCallAdapter(responseType, scheduler)、ResultCallAdapter(responseType, scheduler)。没办法既然有需求我们就回头再看看这两个类型跟SimpleCallAdapter的区别。
ResponseCallAdapter.class@RxJavaCallAdapterFactory.class
static final class ResponseCallAdapter implements CallAdapter<Observable<?>> {
    private final Type responseType;
    private final Scheduler scheduler;
    ResponseCallAdapter(Type responseType, Scheduler scheduler) {
      this.responseType = responseType;
      this.scheduler = scheduler;
    }
    @Override public Type responseType() {  return responseType;  } 
    @Override public <R> Observable<Response<R>> adapt(Call<R> call) {
      Observable<Response<R>> observable = Observable.create(new CallOnSubscribe<>(call)); //note1
      if (scheduler != null) {  return observable.subscribeOn(scheduler); } 
      return observable;
    }
}
1、ResponseCallAdapter相对于SimpleCallAdapter.class它缺少了.lift(OperatorMapResponseToBodyOrError.<R>instance())过程,而正如我们前面分析的,之所以我们之前的SimpleCallAdapter没能接收到Http网络响应的headers(如cookies)就是因为SimpleCallAdapter使用了OperatorMapResponseToBodyOrError操作!所以如果使用ResponseCallAdapter我们的Subscribe就能接收到Response<T>的全部数据了!使用ResponseCallAdapter对应客户端的方法返回类型为Observable<Response<T>>.
ResultCallAdapter.class@RxJavaCallAdapterFactory.class
static final class ResultCallAdapter implements CallAdapter<Observable<?>> {
    private final Type responseType;
    private final Scheduler scheduler;
    ResultCallAdapter(Type responseType, Scheduler scheduler) {
      this.responseType = responseType;
      this.scheduler = scheduler;
    }
    @Override public Type responseType() {  return responseType; } 
    @Override public <R> Observable<Result<R>> adapt(Call<R> call) {
      Observable<Result<R>> observable = Observable.create(new CallOnSubscribe<>(call)) // note1
          .map(new Func1<Response<R>, Result<R>>() { //note2
            @Override public Result<R> call(Response<R> response) {
              return Result.response(response);
            }
          }).onErrorReturn(new Func1<Throwable, Result<R>>() {
            @Override public Result<R> call(Throwable throwable) {
              return Result.error(throwable);
            }
          });
      if (scheduler != null) { return observable.subscribeOn(scheduler); } 
      return observable;
    }
}
1、此处和SimpleCallAdapter、ResponseCallAdapter都是一样的,能接收Subscribe<Response<T>>类型的Subscribe。
2、将Response<T>转换成一个Result<T>对象,Result<T>对象有两个域private final Response<T> response;   private final Throwable error;并有对应的方法返回这两个域。使用ResultCallAdapter对应客户端的方法返回类型为Observable<Result<T>>。

    到此为止我们对RxJavaCallAdapterFactory的介绍已经全部结束了。该工厂能够处理的方法返回值类型为Completable<?> 、Single<?> 和Observable<?>,其它类型交给Retrofit的ArrayList<CallAdapter.Factory>集合中后面的网络请求适配工厂处理。本节主要对Observable<?>进行了介绍,RxJavaCallAdapterFactory会为返回值类型为Observable<?>的方法创建一个CallAdapter<Observable<?>> 对象,而根据Observable内部的数据类型创建如下的继承自CallAdapter<Observable<?>> 的子对象ResponseCallAdapter、ResultCallAdapter和SimpleCallAdapter三个对象,它们的adapt方法返回值类型分别为Observable<Response<T>>、Observable<Result<T>>和Observable<T>三个类型。Observable<Response<T>>向Subscribe发送全部网络响应数据(可以从中读取headers的cookies)、Observable<T>只向Subscribe发送Response.body部分内容——经过转换器转好的T类型数据(不可以从中读取headers的cookies),但是Observable<T>会在内部保证只有在Response.isSuccessful为真时才调用subscribe的onNext方法。


上面介绍完了网络请求适配器工厂——CallAdapter.Factory,接着我们来学习内容转换工厂——Converter.Factory;首先看看Retrofit的内置的内容转换工厂
回顾一下内容工厂都需要实现哪些方法:
public interface Converter<F, T> {
  T convert(F value) throws IOException;
  abstract class Factory {
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } //对响应数据的转换
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null; } //对请求数据的转换
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {  return null;  }  //String类型转换
  }
}

BuiltInConverters.class

在Retrofit.Builder的构造器中就会向converterFactories集合中添加一个 BuiltInConverters对象。
final class BuiltInConverters extends Converter.Factory
responseBodyConverter()@BuiltInConverters.class
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,  Retrofit retrofit) { //note1
    if (type == ResponseBody.class) {
      if (Utils.isAnnotationPresent(annotations, Streaming.class)) {
        return StreamingResponseBodyConverter.INSTANCE;
      }
      return BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
}
1、需要注意的是这里的参数type是通过ServiceMethod的CallAdapter的responseType方法获得的Type;如我们定义的方法返回对象为Observable<Response<T>>,对应type为Response<T>;
该方法能够要求获取ResponseBody、Void类型的返回值进行处理,分别返回BufferingResponseBodyConverter、StreamingResponseBodyConverter、VoidResponseBodyConverter;如果不是ResponseBody类型或者Void类型则返回null交给下一个内容转换器工厂进行处理。
requestBodyConverter()@BuiltInConverters.class
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { 
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) { //note1
      return RequestBodyConverter.INSTANCE;
    }
    return null;
}
1、对于type为Request<T>;Utils.getRawType(type))得到Request
当请求报文的body类型为RequestBody时,该方法返回一个RequestBodyConverter对象。否则交给下一个内容转换器处理。
stringConverter()@BuiltInConverters.class
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,  Retrofit retrofit) { 
    if (type == String.class) {
      return StringConverter.INSTANCE;
    }
    return null;
}
如果类型是String则创建一个StringConverter对象
往下我们依次看看BufferingResponseBodyConverter、StreamingResponseBodyConverter、VoidResponseBodyConverter、RequestBodyConverter和StringConverter的convert方法
StreamingResponseBodyConverter .class@BuiltInConverters.class
static final class StreamingResponseBodyConverter  implements Converter<ResponseBody, ResponseBody> { 
    static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      return value;
    }
}
直接返回传入的ResponseBody类型数据。
BufferingResponseBodyConverter .class@BuiltInConverters.class
static final class BufferingResponseBodyConverter  implements Converter<ResponseBody, ResponseBody> { 
    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {  return Utils.buffer(value); } 
      finally { value.close(); } 
    }
}
以缓存方式读取ResponseBody的内容,一次性全部读取出来。返回创建的ResponseBody,该对象已经将数据全部读取到了内存中。
VoidResponseBodyConverter .class@BuiltInConverters.class
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
    static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
    @Override public Void convert(ResponseBody value) throws IOException {
      value.close();
      return null;
    }
}
直接关闭ResponseBody,返回null
RequestBodyConverter.class@BuiltInConverters.class
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
    @Override public RequestBody convert(RequestBody value) throws IOException {  return value;  } 
}
直接返回RequestBody类型数据
StringConverter.class@BuiltInConverters.class
static final class StringConverter implements Converter<String, String> {
    static final StringConverter INSTANCE = new StringConverter();
    @Override public String convert(String value) throws IOException { return value; } 
}
直接返回String数据
综上我们知道了,Retrofit内置的BuildInConverters只能处理RequestBody、ResponseBody和String类型数据,而且处理方式也简单粗暴,直接返回传入的对象。。。下面我们看看GsonConverterFactory内部是不是复杂些。这是我们最经常使用的一个内容转换器工厂,将javaBean数据转换为JSON数据格式的String数据。

GsonConverterFactory.class

public final class GsonConverterFactory extends Converter.Factory
GsonConverterFactory()@GsonConverterFactory.class
private final Gson gson; //操作实体
private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
}
public static GsonConverterFactory create() { return create(new Gson()); }
public static GsonConverterFactory create(Gson gson) {  return new GsonConverterFactory(gson); }
responseBodyConverter()@GsonConverterFactory.class
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { 
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); //note1
    return new GsonResponseBodyConverter<>(gson, adapter);
}
1、对于type值我们之前已经讲过了,如果方法返回对象为Observable<Response<T>>,这里的type对应Response<T>;com.google.gson.reflect.TypeToken会对Response<T>进行分离得到Response和T;然后获取一个预期类型的适配器。创建一个GsonResponseBodyConverter对象
 requestBodyConverter()@GsonConverterFactory.class
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { 
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); //note1
    return new GsonRequestBodyConverter<>(gson, adapter);
}
1、大体上跟之前的responseBodyConverter一样,也是先得到一个预期类型的适配器,只是这里创建了一个GsonRequestBodyConverter对象
下面我们分别看看GsonResponseBodyConverter和GsonRequestBodyConverter的convert方法。

GsonResponseBodyConverter.class

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;
  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream()); //note1
    try {  return adapter.read(jsonReader); } //note2
    finally { value.close(); } 
  }
}
1、将待转换的ResponseBody数据以字符char的方式读取
2、利用构造GsonResponseBodyConverter对象时传入的TypeAdapter将ResponseBody的字符流转换成T对象

GsonRequestBodyConverter.class

final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
  private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
  private static final Charset UTF_8 = Charset.forName("UTF-8");
  private final Gson gson;
  private final TypeAdapter<T> adapter;
  GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }
  @Override public RequestBody convert(T value) throws IOException {
    Buffer buffer = new Buffer(); //note1
    Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); //note2
    JsonWriter jsonWriter = gson.newJsonWriter(writer);
    adapter.write(jsonWriter, value); //note3
    jsonWriter.close();
    return RequestBody.create(MEDIA_TYPE, buffer.readByteString());//note4
  }
}
1、创建一个okio.Buffer对象
2、以UTF_8编码方式向buffer中写入数据
3、将传入T类型的数据进行JSON转换,并以UTF_8编码方式写入buffer
4、buffer以比特形式读取,写入RequestBody中,同时对应的MediaType为"application/json; charset=UTF-8"

    以上是对GsonConverterFactory的简单介绍,因为具体的转换是Gson的事情,涉及到json的格式细节问题,已经不是Retrofit的内容了,因此不再往下深入,如有兴趣可以看另一篇博客《 Json FastJson Gson介绍与使用》。GsonConverterFactory只重写了requestBodyConverter()和responseBodyConverter()两个方法,并没有重写stringConverter()方法。因为对于String类型的转换已经被BuildInConverters拦截了,因此GsonConverterFactory不再需要对String类型进行转换。这里需要注意的是requestBodyConverter()和responseBodyConverter()两个方法可以说对于任何参数来者不拒,它绝对不会返回null,它不对传入该方法的Type type, Annotation[] annotations数据进行任何判断。因此Retrofit作者——jake-wharton大神强调一定将GsonConverterFactory添加到Retrofit的ArrayList<Converter.Factory>集合的末尾。

附录

还记得在parseResponse()@OkHttpCall.class中对有如下一段代码
Response<T> parseResponse(okhttp3.Response rawResponse) {
    ....
    int code = rawResponse.code();
    if (code < 200 || code >= 300) { //响应执行失败
     ResponseBody bufferedBody = Utils.buffer(rawBody);
     return Response.error(bufferedBody, rawResponse);
    }
    if (code == 204 || code == 205) { //响应执行成功 但是没有返回数据body为空
      return Response.success(null, rawResponse);
    } ....
}
方法中对网络的状态码进行了判断,但是很多童鞋可能不太通这些状态码的含义,特此从网上趴下来一些常用的状态码附录在此,方便学习。
Http状态码:
  • 成功(2字头)
    • 200 OK:请求成功、其后是对GET和POST请求的应答文档
    • 202 Accepted:供处理的请求已被接受,但是处理未完成。
    • 204 No Content:没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
    • 205 Reset Content:没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
    • 206 Partial Content:断点续传,客户发送了一个带有Range头的GET请求,服务器完成了它。
  • 重定向(3字头)
    • 300 Multiple Choices:多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
    • 301 Moved Permanently:所请求的页面已经转移至新的url。
    • 302 Move temporarily:所请求的页面临时转移至新的url。如果这不是一个 GET 或者 HEAD 请求,那么浏览器禁止自动进行重定向,除非得到用户的确认
    • 304 Not Modified:客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
  • 请求错误(4字头)
    • 400 Bad Request:语义有误、请求参数有误。
    • 403 Forbidden:服务器已经理解请求,但是拒绝执行它。
    • 404 Not Found:请求失败,请求所希望得到的资源未被在服务器上发现
  • 服务器错误(5、6字头)
    • 500 Internal Server Error:请求未完成。服务器遇到不可预知的情况。


Retrofit的使用与深入学习(下)

标签:

原文地址:http://blog.csdn.net/evan_man/article/details/51320637

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!