本節是《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默認網絡請求適配器ExecutorCallAdapterFactory和RxJavaCallAdapterFactory進行介紹,隨後介紹Retrofit的默認內容轉換器BuiltInConverters和GsonConverterFactory。在此需要在此強調的是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;
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方法
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類型數據。
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,該對象已經將數據全部讀取到了內存中。
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:請求未完成。服務器遇到不可預知的情況。