我们以网上很流行的天气预报的接口为例,模拟一个Retrofit
的使用例子,首先我们需要一个定义请求的接口类WeatherService.java
:
public interface WeatherService {
@GET("/Ecalender/api/v2/weather")
Call<WeatherData> getWeather(@Query("date") String date, @Query("citykey") String citykey);
@GET("/Ecalender/api/v2/weather")
Observable<WeatherData> getWeatherObservable(@Query("date") String date, @Query("citykey") String citykey);
}
WeatherService.java
例举了两种不同的返回方式,下面我们使用标准的Call
的返回方式举例调用过程代码,
private void getWeather() {
retrofit = new Retrofit.Builder()
.baseUrl("http://v.juhe.cn/calendar/day")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
service = retrofit.create(WeatherService.class);
String nowDate = new SimpleDateFormate("YYYY-MM-DD").format(new Date());
Call<WeatherData> result = service.getWeather(nowDate, "101010100");
try {
Response<WeatherData> r = result.execute();
WeatherData data = r.body();
Log.e("David", "ResponseBody data = " + data);
if (data != null) {
Log.e("David", "RxLoaderCallback data = " + data.weatherinfo.desc);
Log.e("David", "RxLoaderCallback data = " + data.result.lunarYear);
Log.e("David", "RxLoaderCallback data = " + data.result.weekday);
}
} catch (IOException e) {
e.printStackTrace();
}
}
Retrofit
调用步骤:
Retrofit.Builder
配置好各项参数,然后调用build()
创建Retrofit
对象。WeatherService.class
传递给Retrofit
对象,然后创建WeatherService
代理对象service
。WeatherService
代理service
对象调用方法getWeather()
得到Call
对象result
。Call
对象result
的excute()
方法执行http网络请求,得到返回结果Response
对象r
。Response
对象r
的body()
方法得到我们真正需要的WeatherData
对象。首先new
了一个Retrofit.Builder
对象,然后配置各种参数,这里类似与setter
的功能,其中参数baseUrl
是必须要配置的,不然会报错。最后调用Retrofit.Builder
的build()
方法生成Retrofit
对象,其内部也是使用了new Retrofit()
的方式创建新对象。。
public static final class Builder {
......
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
......
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
}
得到Retrofit
对象后,通过Retrofit
对象的create()
方法创建Http
的代理对象,
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();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable 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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
当我们通过代理对象发起请求的时候会进入上面代理对象的InvocationHandler
对象的invoke()
方法中,然后会进入Retrofit
对象的loadServiceMethod()
方法:
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
在方法中,会首先判断是否有缓存ServiceMethod
对象,如果有缓存,则直接返回之前缓存的ServiceMethod
对象,否则调用ServiceMethod.parseAnnotations()
创建新的ServiceMethod
对象,并放入缓存。我们看看ServiceMethod
是怎样创建新的对象的:
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
.......
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
方法内部是通过HttpServiceMethod
来创建的,我们在进入HttpServiceMethod
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
........
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
........
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
根据我们上面的调用例子,没有Kotlin
支持,所以直接返回的就是HttpServiceMethod
子类CallAdated
对象,注意此时我们返回的HttpServiceMethod
对象创建时传入了okhttp3.Call.Factory
对象,CallAdapter
对象因为没有配置CallAdapter.Factory
所以使用的默认,直接返回Call
,后面会使用到。
承接上面的代理对象的请求调用其实是调用了我们刚刚生成的HttpServiceMethod
对象的invoke()
方法,
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
在HttpServiceMethod
对象的invoke()
方法中,新建了一个OkHttpCall
对象,然后通过适配方法adapt
转换成需要的目标接口类型。根据我们上面的demo调用例子,也就是执行了CallAdated
对象的adapt()
,
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
这里的CallAdapter
对象因为没有配置CallAdapter.Factory
所以使用的默认,直接返回Call
,也就是上面第3步得到Call
对象result
。其实返回的也是一个OkHttpCall
对象。
上面地4步,Call
对象result
的excute()
也就是发起网络请求,实际执行的是OkHttpCall
对象的excute()
方法
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
.......
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
里面通过createRawCall()
方法调用了OkHttpClient
的newCall()
创建了一个RealCall
对象:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
然后OkHttpCall
对象的excute()
方法最后一行,先调用excute()
方法执行网络请求。再跟进去就是OkHttp
的网络请求细节了,所以不再跟进。执行完OkHttp
的网络请求后,胡调用parseResponse()
方法对返回结果进行处理。
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
......
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
.......
}
}
可以看到请求成功后,会将返回成功body
转换成目标类型之后放入Retrofit
中的Response
的body
。所以我们上面在第5步的时候是通过Response
对象r
的body()
方法得到我们真正需要的WeatherData
对象。
由于个人水平可能有限,如果上述博文有不正确的地方,欢迎大家指正