Retrofit的使用與深入學習(下)


注意:以下分析都是基於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()方法解除綁定的原因,即斷開網絡連接,回收網絡資源。

到此爲止我們分析完了[email protected]的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 [email protected]
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 [email protected]
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 [email protected]
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
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類型數據
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:請求未完成。服務器遇到不可預知的情況。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章