Retrofit做爲時下android裏比較經常使用的庫,特別是結合着rxjava 後用起來非常酸爽啊,本篇就是剖析一下retrofit2.0結合adapter-rxjava,converter-gson後整個流程是怎樣串起來的,以及源碼的解析java
retrofit源碼地址 圖一就是今天的重點了,圖二是發起請求對應的註解種類了 android
都知道retrofit實際調用的是okhttp。也能夠說retrofi就是在okhttp的基礎上包了一層,經過大量的設計模式進行功能模塊的解耦,使得整個整個流程變得整潔和清爽、git
閱讀一個三方庫 先從接口入手,先了解一下上層大體提供了哪些功能有助於快速理解github
**Call **設計模式
對於okhttp 的call的的一個再包裝,也是真正發出請求的對象接口
public interface Call<T> extends Cloneable {
Response<T> execute() throws IOException;
void enqueue(Callback<T> callback);
boolean isExecuted();
void cancel();
Call<T> clone();
/**返回的是okhttp的Request. */
Request request();
}
複製代碼
**CallAdapter **api
//能夠把Call對象轉化爲另一個對象,如Observable,Flowable
public interface CallAdapter<R, T> {
//Type 返回值泛型的對象類型如:Flowable<Response<Bean>>裏的Response<Bean>
Type responseType();
//傳入一個R返回一個T,T:返回值 一個Call或者Flowable
T adapt(Call<R> call);
//工廠裏提供三個方法 1:根據返回值returnType獲取具體請求的CallAdapter 2:根據返回值type 獲取泛型裏的數據類型
// 3:經過type獲取class的類型,獲取整個返回值的類型 如Observable<T>,Flowable<T> ,Call<T>
// 2,3 均爲工具類
abstract class Factory {
//abstract抽象方法,必定要被實現
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
**Callback **
請求回調
**Converter **
數據轉換適配器,能夠對請求的數據或者響應的數據再度處理
public interface Converter<F, T> {
T convert(F value) throws IOException;
/** Creates {@link Converter} instances based on a type and target usage. */
abstract class Factory {
/**
* 傳入ResponseBody返回t,對響應數據進行解析,converter-gson會重寫此方法
*/
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
*
*傳入T返回ResponseBody 對請求數據進行處理,只有在 申明@Body, @Part ,@PartMap
*這三個註解時纔會生效
*
*/
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
/** *
* {@link Field @Field}, {@link FieldMap @FieldMap} values,
* {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
* {@link Query @Query}, and {@link QueryMap @QueryMap} values.
對以上註解的值進行處理 而已已經被BuiltInConverters(默認解析類)類重寫,外部重寫無效
*/
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
/**
工具類做用與CallAdapter裏的同樣
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
複製代碼
獲取 retrofit 實例以及添加上rxjava 請求適配器和converter-gson解析器
public Retrofit getRetrofit(String baseurl, OkHttpClient client) {
if (client == null)
client = getOkHttpClient();
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl(baseurl);//baseurl路徑
builder.client(client)//添加客戶端
.addConverterFactory(GsonConverterFactory.create());//添加Gson格式化工廠
//添加 rxjava
builder.addCallAdapterFactory(RxJava2CallAdapterFactory
.createWithScheduler(Schedulers.from(AppExecutor.instance())));
retrofit = builder.build();
return retrofit;
}
//自定義的通用解析類,t爲data內具體對象,msg和code爲公用數據部分
public class Response<T> {
private T data;
private String msg;
private String code;
}
//定義接口類
public interface ApiService {
/**
* 測試數據
*/
@GET("data/福利/{num}/{page}")
Flowable<Response<Bean>> getGirlList(@Path("num") int num, @Path("page") int page);
}
//獲取ApiService
ApiService apiservice=getRetrofit(baseurl,OkHttpClient).create(serviceClass)
//發起請求,(這裏未經封裝,正常使用要再封裝下)
apiservice.getGirlList(1,2).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(new ResourceSubscriber<Response<Bean>>() {
@Override
public void onNext(Response<Bean> o) {
//結果回調
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
})
複製代碼
Retrofit實例是使用建造者模式經過Builder類進行建立的數組
核心類
這裏只關心Android平臺下的java8的不看
static class Android extends Platform {
// Guarded by API check.
@Override
boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
/**
* ExecutorCallAdapterFactory默認工廠類,
* if (getRawType(returnType) != Call.class) {
* return null;}
*只解析返回類型爲Call.class的數據,即原生retrofit的返回值都會使用這個工廠,緣由後面
*/
@Override
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return singletonList(new ExecutorCallAdapterFactory(callbackExecutor));
}
/**
* android平臺 默認爲MainThreadExecutor,
*/
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
**默認CallAdapter實體類 提供了只解析解析返回Call.class類型的CallAdapter **
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
//android平臺下 默認爲MainThreadExecutor,數據切換到主線程,okhttp默認是在子線程
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
// 默認爲 ExecutorCallAdapterFactory,只解析返回類型爲Call.class的數據,即原生retrofit的返回值
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());//默認數據解析類
當返回類型爲ResponseBody時適用(即:原生okhttp)
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());;//defaultConverterFactories實際上什麼也沒有,默認的解析行爲都在BuiltInConverters類
//unmodifiableList() :返回一個只能被訪問不能被修改的集合
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
複製代碼
而後看下 GsonConverterFactory gson解析類 重寫了responseBodyConverter和requestBodyConverter 實際都經過 gson 把返回數據或者請求數據解析成指定的type緩存
public final class GsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
複製代碼
**而後看下 RxJava2CallAdapterFactory rxjava適配器 實現get方法 只解析 返回類型爲 Observable.class ,isFlowable , isSingle ,isMaybe四類bash
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
/**
* Returns an instance which creates synchronous observables that do not operate on any scheduler
* by default.
*/
public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}
/**
* Returns an instance which creates asynchronous observables. Applying
* {@link Observable#subscribeOn} has no effect on stream types created by this factory.
*/
public static RxJava2CallAdapterFactory createAsync() {
return new RxJava2CallAdapterFactory(null, true);
}
/**
* Returns an instance which creates synchronous observables that
* {@linkplain Observable#subscribeOn(Scheduler) subscribe on} {@code scheduler} by default.
*/
public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler, false);
}
private final Scheduler scheduler;
private final boolean isAsync;
private RxJava2CallAdapterFactory(Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
}
複製代碼
**繼續 Retrofit 類核心方法 **async
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);//service必須爲接口類,且方法數>0
if (validateEagerly) {//validateEagerly 是否預解析service裏全部方法註解,正常是使用一個方法才解析一個,而後放到緩存裏,下次直接用緩存
eagerlyValidateMethods(service);
}
//動態代理,傳入一個接口返回一個對象
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//platform.isDefaultMethod(method) 平臺下 痕爲fasle,兼容java8的不關心
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
終於到重點 loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
複製代碼
**先看 loadServiceMethod(method) **
核心方法 result = ServiceMethod.parseAnnotations(this, method);
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
先看一下RequestFactory 類 經過解析註解 提供 okhttp3.Request(真正的請求)
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
private final Method method; // 調用的service內方法名字
private final HttpUrl baseUrl;
final String httpMethod; // 請求方法:get.post.put...
private final String relativeUrl;//實際的url: baseUrl+ 後綴默認
private final Headers headers;// 頭信息
private final MediaType contentType;//contentType
private final boolean hasBody;// post方式纔有
private final boolean isFormEncoded;//是不是表單提交
private final boolean isMultipart;//帶文件的鍵值對提交
private final ParameterHandler<?>[] parameterHandlers;//這個類很重要,負責根據不一樣的註解類型 去把傳入的參數和註解的value 作相應的拼接處理
//retrofit裏關於註解的解析 都在Builder 裏
static final class Builder {
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();//獲取方法上的註解
this.parameterTypes = method.getGenericParameterTypes();//傳入參數對應的類型
this.parameterAnnotationsArray = method.getParameterAnnotations();//參數註解,二維數組,每一個參數上的註解都是數組
}
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
//確認請求方式 並對傳入註解的value作校驗,根據請求方式肯定這次請求是否有body
parseMethodAnnotation(annotation);
}
//這裏開始解析方法上的註解參數,能夠有多個參數而後 每一個參數上能夠跟多個註解,全部是個二維數組,說是這樣說,可是實際操做的時候 一個參數上只容許跟一個註解,多了會包錯
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
}
return new RequestFactory(this);
}
}
}
複製代碼
**看下 parseParameter() **
/**
* 解析參數註解
*
* @param p 當前參數的位置
* @param parameterType 參數對應的類型
* @param annotations 參數對應的註解,retrofit只容許有一個
* @return
*/
private ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
//一個參數上只容許跟一個註解 多了會拋異常
if (result != null) {
throw parameterError(method, p,
"Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
}
if (result == null) {
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
複製代碼
再看 parseParameterAnnotation()