本文将从Retrofit 官网上提供的一个简单的例子来大致看一下Retrofit的代码
Demo
interface:
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(@Path("owner") String owner, @Path("repo") String repo);
retrofit 网络请求,异步:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service=retrofit.create(GitHubService.class);
Call<List<Contributor>> repos = service.contributors("square", "retrofit");
repos.enqueue(new Callback<List<Contributor>>() {
@Override
public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
List<Contributor> contributors = response.body();
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
@Override
public void onFailure(Call<List<Contributor>> call, Throwable t) {}
});
这是Retrofit 提供的一个最简单的Demo,运行结果就不展示了。
代码分析
Retrofit 初始化
retrofit 可以通过构造体初始化,也可以通过Retrofit的内部类Builder class 进行初始化,首先说明Builder创建Retrofit这种设计模式不是建造者模式,而是门面模式。有时间可以写一篇门面模式的博客。,其实这种形式在android中挺常见,包括AlertDialog 初始化。这种形式的好处在于:
- 流式调用模式,代码更加清晰
下面开始分析一下Retrofit的代码
首先Builder 构造体中通过Platform的findPlatform()方法决定当前代码的运行平台。
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();//如果是android设备SDK版本肯定不为0
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
同时Platform 提供defaultCallbackExecutor 方法,该方法是决定异步网络请求回调线程。我们都知道Android 中网络回调是在主线程上(更新UI),看一下Android 代码:
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
在Android类中复写了defaultCallbackExecutor ,defaultCallAdapterFactory方法。我们知道android 中网络请求是不允许在主线程上的,而UI 更新是必须在主线程上。我们常见网络请求就是为了更新UI,所以我们需要一个回调将网络线程上请求的数据,发送到主线程上,所以在retrofit中callBack(回调) 通过获取主线程Handler将信息传递出去,这样就确保Retrofit 回调在主线程上。
而 defaultCallAdapterFactory 这个方法为什么要将callBack参数传递?ExecutorCallAdapterFactory,根据这个类名我们也大概知道这是一个CallAdapter的工厂类,代码如下:
ExecutorCallAdapterFactory
@Override
public 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);
}
};
}
通过阅读代码可以看到是通过get方法返回CallAdapter对象,ExecutorCallAdapterFactory里面有一个内部类ExecutorCallbackCall,它初始化的时候真正的用到了callbackExecutor ,
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "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);
}
});
}
});
}
看到enqueue 这个方法, 我会想到OKHttp中的异步请求,其实还真是这样,我们知道Retrofit 网络请求默认是通过Okhttp进行网络请求的,在请求网络结束之后分别有两个方法回调,onResponse 和 onFail ,这两个方法的回调信息都是callbackExecutor.execute 发送的,也就是通过handler 将信息发送出去。到这Platform这个类就算说完了,平台不同相应回调实现也不会不同。
好了,Builder的构造体看完了,接着看Builder的方法。通过流式布局的形式,通过调用相应的方法给Retrofit中的变量,最后通过build() 创建出Retrofit对象。
看一下Builder中的方法:
- public Builder baseUrl(HttpUrl baseUrl) //设置网络请求地址
- public Builder addConverterFactory(Converter.Factory factory) //转换工厂 (GsonConverterFactory , RxJava2CallAdapterFactory)
- public Builder addCallAdapterFactory(CallAdapter.Factory factory)
- public Builder callbackExecutor(Executor executor) //回调执行器
- public Builder client(OkHttpClient client)
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();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
其中Call.Factory 是通过client() 赋值的,如果未通过该方法赋值,则会使用默认OkhttpClient 。Retrofit的初始化就到这!