阅读此文前请先阅读Retrofit+okhttp网络框架介绍
从上文中我们已经了解通过如下代码即可得到返回给我们call 以及 response对象,今天我们通过源码来分析这个过程是如何实现的。
/**
* 获取天气数据
* @param cityname
* @param key
* @return
*/
@GET("/weather/index")
Call<WeatherData> getWeatherData(@Query("format") String format, @Query("cityname") String cityname, @Query("key") String key);
private static final String ENDPOINT = "http://v.juhe.cn";
private static final Retrofit sRetrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
//.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作为回调适配器
.build();
private static final ApiManagerService apiManager = sRetrofit.create(ApiManagerService.class);
ApiManager.getWeatherData(format,city).enqueue(new Callback<WeatherData>() {
@Override
public void onResponse(Call<WeatherData> call, Response<WeatherData> response) {
mWeatherOnListener.onSuccessData(response.body());
}
@Override
public void onFailure(Call<WeatherData> call, Throwable t) {
mWeatherOnListener.onFailure(t);
}
});
分析流程图
ok,那我们就开始按照以上流程图,来揭开Retrofit的面纱,下面逐步介绍,最后在简单总结。
源码分析
1、Retrofit的构建
这里是通过构造者模式进行构建retrofit对象,好在其内部的成员变量比较少,我们直接看build()方法。
public Builder() {
this(Platform.get());
}
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);
}
- baseUrl必须指定,这个是理所当然的;
- 然后可以看到如果不着急设置callFactory,则默认直接new
OkHttpClient(),可见如果你需要对okhttpclient进行详细的设置,需要构建OkHttpClient对象,然后传入; - 接下来是callbackExecutor,这个想一想大概是用来将回调传递到UI线程了,当然这里设计的比较巧妙,利用platform对象,对平台进行判断,判断主要是利用Class.forName(“”)进行查找。
- 如果是Android平台,会自定义一个Executor对象,并且利用Looper.getMainLooper()实例化一个handler对象,在Executor内部通过handler.post(runnable)。
- 接下来是adapterFactories,这个对象主要用于对Call进行转化,基本上不需要我们自己去自定义。
- 最后是converterFactories,该对象用于转化数据,例如将返回的responseBody转化为对象等;当然不仅仅是针对返回的数据,还能用于一般备注解的参数的转化例如@Body标识的对象做一些操作,后面遇到源码详细再描述。
Class.forName(“”)查找的源码,值得学习,以后用来判断平台可以复制以下源码。
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("org.robovm.apple.foundation.NSObject");
return new IOS();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
2、外观模式(门面模式)
Retrofit给我们暴露的方法和类不多。核心类就是Retrofit,我们只管配置Retrofit,然后做请求。剩下的事情就跟上层无关了,只需要等待回调。这样大大降低了系统的耦合度。对于这种写法,我们叫外观模式(门面模式)。
几乎所有优秀的开源library都有一个门面。比如 Glide.with() ImageLoader.load() Alamofire.request() 。有个门面方便记忆,学习成本低,利于推广品牌。 Retrofit的门面就是 retrofit.create().