一、適用人羣。會使用Retrofit,想更好更全面的瞭解Retrofit的童鞋。
二、解析
1、獲取Retrofit實例
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
成員變量解釋
1)callFactory 處理網絡請求的工廠類,依賴於okhttp3.Factory
2)baseUrl 網絡請求的基礎地址
3)converterFactories 實例類轉化工廠
4)adapterFactories CallAdapter生成工廠
5)callbackExecutor 回調的執行者,一個executor
6)validateEagerly 是否提前驗證methods是實現自接口
這裏着重說下converterFactories 和adapterFactories 的區別和作用
在Rxjava中,網絡請求的接口一般是這種形式
public interface HttpLogin {
@POST("account/login")
XXX<YYY> login(@Body ZZZ body);
}
converterFactories 是負責文字和實體類互相轉化,需要把http返回的body轉成yyy實體類,以及把ZZZ實體轉成字符串。
adapterFactories 是負責生成XXX實體類的適配器。在DefaultCallAdapterFactory.java文件中可以看出陸默認的僅支持XXX爲retrofit2.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) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
可以看出:
1) 必須設置baseUrl
2)默認使用okhttp3.OkHttpClient使用網絡請求工廠
3)callbackExecutor回調執行器用的是MainThreadExecutor,簡單的說就是在主線程回調
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
4)adapterFactories默認添加了retrofit2.DefaultCallAdapterFactory
DefaultCallAdapterFactory.class
*/
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//可以看出支持的返回類型僅爲retrofit2.Call,其他類型就不支持了
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 call;
}
};
}
}
5)converterFactories默認是個retrofit2.BuiltInConverters
retrofit2.BuiltInConverters代碼太多,就只貼出關鍵的
//可以看出只支持入參爲ResponseBody類型
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
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;
}
6)validateEagerly默認flase;
2、根據上面的要求創建一個請求接口
public interface HttpLogin {
@POST("account/login")
retrofit2.Call<ResponseBody> login(@Body RequestBody body);
}
1) retrofit2.Call login = retrofit.create(HttpLogin.class)
.login(RequestBody.create(MediaType.parse(“Application/json”), “{\”account\”:112333}”));
這裏看下Retrofit.create(final Class service) 函數
public <T> T create(final Class<T> service) {
//驗證service。必須是接口而且沒有繼承其他接口
Utils.validateServiceInterface(service);
if (validateEagerly) {
//把接口方法存到緩存中
eagerlyValidateMethods(service);
}
//動態代理
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
//如果該方法在的類.class是Object.class
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//如果是平臺的默認方法,在Android Platform恆爲false。
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//將方法存緩存,然後取。。。就這樣
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
這裏出現了ServiceMethod,發現對它不瞭解的話就無法進行下去了。我們來看看
ServiceMethod類
public ServiceMethod.Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//方法的註解集
this.methodAnnotations = method.getAnnotations();
//方法的參數類型集
this.parameterTypes = method.getGenericParameterTypes();
//方法的參數註解集(@path.etc)
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
//這裏只展現了一些核心代碼
public ServiceMethod build() {
//在轉化器集合找到可以處理該返回類型轉化的轉化器。沒有找到,就會在裏面拋異常
callAdapter = createCallAdapter();
//返回類型
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
//在轉化器集合找到可以處理該返回類型轉化的轉化器。沒有找到,就會在裏面拋異常
responseConverter = createResponseConverter();
//解析接口方法註解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//解析接口的入參與入參註解
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
}
return new ServiceMethod<>(this);
}
ServiceMethod(Builder<T> builder) {
//返回的類型的工廠類
this.callFactory = builder.retrofit.callFactory();
//請求的適配器
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
//返回類型的轉成實體類的轉化器
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
//請求的實際路徑。
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
這時候得到了retrofit2.Call login對象,這個call很像Okhttp裏的Call;
這時候調用
login.enqueue(new retrofit2.Callback<ResponseBody>() {
@Override
public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
System.out.println("onResponse ");
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
System.out.println("onFailure " + t.getMessage());
}
});
實際上調用了retrofit2.OkHttpCall<T>. enqueue(final Callback<T> callback)方法
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//這裏是調用了okhttp.call的方法
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
執行完。控件臺打印出
onResponse
{"code":999999,"des":"參數錯誤[密碼不能爲空]"}
Process finished with exit code 0