Retrofit使用
若要請求api
https://api.github.com/users/{user}/repos
需要先創(chuàng)建一個接口
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
然后創(chuàng)建一個Retrofit對象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.build();
GitHubService service = retrofit.create(GitHubService.class);
可以看到通過retrofit.create()方法,retrofit為我們創(chuàng)建了一個GitHubService的實現(xiàn),感覺很不可思議。
緊接著就可以通過這個GitHubService的實現(xiàn)對象去請求網(wǎng)絡了
Call<List<Repo>> repos = service.listRepos("octocat");
// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();
看到這里總是很疑惑,retrofit是如何用我們提供的接口來為我們創(chuàng)建出一個實例的呢?
Retrofit調(diào)用流程
從上面我們可以看到service實例是通過retrofit.create()方法獲得的,那我們不看一下這個create()方法
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> 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.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadMethodHandler(method).invoke(args);
}
});
}
可以看到該方法返回的并不是一個service接口的實例,而是一個動態(tài)代理對象,而他又是怎么通過動態(tài)代理去發(fā)送網(wǎng)絡請求的呢?我們就需要查看
return loadMethodHandler(method).invoke(args);
這行代碼的返回結(jié)果了,去查看loadMethodHandler()方法
private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();
MethodHandler loadMethodHandler(Method method) {
MethodHandler handler;
synchronized (methodHandlerCache) {
handler = methodHandlerCache.get(method);
if (handler == null) {
handler = MethodHandler.create(this, method);
methodHandlerCache.put(method, handler);
}
}
return handler;
}
可以看到該方法先去試圖從methodHandler的緩存map中去尋找相應的methodHandler,若不存在再去創(chuàng)建對應方法的MethodHandler,獲得了相應的MethodHandler實例后再去調(diào)用去invoke()方法來發(fā)送請求。
繼續(xù)查看MethodHandler的invoke()方法
Object invoke(Object... args) {
return callAdapter.adapt(
new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
}
其中callAdapter.adapt()方法負責把service中的返回類型轉(zhuǎn)換成其他類型,例如RxJavaCallAdapter把返回結(jié)果轉(zhuǎn)換成了Observable類型
可以看到adapt方法中傳入了一個OkHttpCall參數(shù),而最后發(fā)送出網(wǎng)絡請求的正是在該類的
@Override public void enqueue(final Callback<T> callback)
@Override public Response<T> execute() throws IOException
這兩個方法中。相關(guān)的Http請求信息則封裝在了requestFactory這個對象中。
這樣整個流程就清楚了,可以看到這與我們一般使用動態(tài)代理的方法是不同的。這里對動態(tài)代理的使用是通過調(diào)用動態(tài)代理對象的相應方法,去生成一個Http請求再來發(fā)送這個請求。而service接口中方法的信息則是通過反射來得到的。
</br>