Retrofit 原理解析与自定义实现详解手机开发

Retrofit 结合OkHttp构成了当前非常流行的Android的网络框架。而Retrofit对OKHttp进行了一层封装,可能入手的门槛高一点,但是使用习惯以后可以说是非常的简洁和高效。

Retrofit 还可以跟 Rxjava 转化成Obserable,形成了链式编程风格,深得我心。

Retrofit的基本源码流程:

  1. 动态代理获取Method
  2. Method从提取出注解参数
  3. 执行网络操作
  4. 转换成对应结果

本文不会直接跟着代码走完所有流程,只拿出重要的几点分析。

在开始分析之前,先写个简单的例子,我们申明一个接口 getServiceName

public interface ServiceApi {
    
	@GET 
	Call<String> getServiceName(); 
} 

下面来看,Retrofit 如何解析ServiceApi并进行网络操作。

Retrofit类定义了几个重要的变量:

  // Retrofit 
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); 
  final okhttp3.Call.Factory callFactory; 
  final HttpUrl baseUrl; 
  final List<Converter.Factory> converterFactories; 
  final List<CallAdapter.Factory> callAdapterFactories; 
  final @Nullable Executor callbackExecutor; 

Retrofit的第一步就是获取

  • ServiceMethod对应着根据Method解析出的注解、返回的结果类型等,并缓存到了serviceMethodCache,避免每次都需要重新解析

  • callFactory 是okhttp创建call的类

  • baseUrl

  • converterFactories 是一个集合,负责对网络请求的RequestBody 和网络请求结果 ResponseBody的转换,例如我们经常使用的GsonConverterFactory

  • callAdapterFactories 也是一个集合,负责对最后的返回结果的封装或转换,例如我们经常使用的RxJava2CallAdapterFactory

  • callbackExecutor 是负责执行,Android默认执行器是利用handler抛到主线程执行回调结果。所以我们会看到retrofit的结果都在主线程中。

1. 动态代理获取Method

retrofit之所以利用动态代理,有两个目的:

  1. 可以实例化上面ServiceApi这个接口,直接调用getServiceName进行网络请求;
  2. 可以通过动态代理拿到对应的Method,也就可以拿到Method上的注解,进行参数解析;

除了这种动态代理的实现方式以外,要想达到一样的效果的就是类似ButterKnife注入框架,在编译时候利用AnnotionProcessor生成ServiceApi实现类。因为是编译期生成,所以不会影响运行效率,但是也会存在其他问题。

public <T> T create(final Class<T> 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]; 
 
          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 loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 
          } 
        }); 
  } 

这里直接看最后的一句:

loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 

2. Method从提取出注解参数

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; 
  } 

parseAnnotations()的作用:

  1. 解析注解转换成各种http参数
  2. 解析出返回类型Type
  3. 找出对应的CallApater
  4. 找出对应的Converter
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( 
Retrofit retrofit, Method method, RequestFactory requestFactory) {
 
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; 
boolean continuationWantsResponse = false; 
boolean continuationBodyNullable = false; 
Annotation[] annotations = method.getAnnotations(); 
Type adapterType; 
if (isKotlinSuspendFunction) {
 
Type[] parameterTypes = method.getGenericParameterTypes(); 
Type responseType = Utils.getParameterLowerBound(0, 
(ParameterizedType) parameterTypes[parameterTypes.length - 1]); 
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
 
// Unwrap the actual body type from Response<T>. 
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType); 
continuationWantsResponse = true; 
} 
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType); 
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); 
} else {
 
adapterType = method.getGenericReturnType(); 
} 
CallAdapter<ResponseT, ReturnT> callAdapter = 
createCallAdapter(retrofit, method, adapterType, annotations); 
Type responseType = callAdapter.responseType(); 
... 
Converter<ResponseBody, ResponseT> responseConverter = 
createResponseConverter(retrofit, method, responseType); 
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); 
} 
} 

3. 执行网络操作

loadServiceMethod(method).invoke(args != null ? args : emptyArgs); 

ServiceMethod.invoke()进行了网络操作和转换操作,不过他是个抽象方法,直接看他的子类HttpServiceMethod

// HttpServiceMethod 
final @Nullable ReturnT invoke(Object[] args) {
 
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); 
return adapt(call, args); 
} 
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args); 

具体看CallAdapted实现类,他就是一个封装类,封装了CallAdapter。

转发调用了CallAdapter的adapt,这里的CallAdapter是由上面parseAnnotations()中找出对应的CallAdapter。

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
 
private final CallAdapter<ResponseT, ReturnT> callAdapter; 
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, 
Converter<ResponseBody, ResponseT> responseConverter, 
CallAdapter<ResponseT, ReturnT> callAdapter) {
 
super(requestFactory, callFactory, responseConverter); 
this.callAdapter = callAdapter; 
} 
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
 
return callAdapter.adapt(call); 
} 
} 

callAdapter.adapt()根据不同的具体callAdapter执行不同的操作。

其中默认的实现也只是执行了Okhttp的Call.enque()流程。

再回来看HttpServiceMethod 的invoke()方法,内部主要是构造了一个retrofit2.OkHttpCall对象,里面封装了OkHttp 的Call对象、Converter,其实就是封装了整个Okhttp的请求流程,最后对Converter结果转换。

这里不贴代码了。

实现一个简单的Retrofit框架

自定义Retrofit 需要做到:

  1. 动态代理
  2. 解析参数
  3. 执行操作和转换结果,返回对应类型的结果

定义一个参数注解

 
@Retention(RetentionPolicy.RUNTIME) 
@Target({
ElementType.METHOD}) 
public @interface CustomParam {
 
int value(); 
} 

CustomParam就是最简单的一个注解参数,value是一个整数,对应着是Retrofit各种复杂网络参数配置。

定义一个执行者CallAdapter接口

public abstract class CustomCallAdapter<P, R> {
 
public abstract R adapt(P params); 
public abstract Type getResponseType(); 
} 

CustomCallAdapter是一个CallAdapter的简化版本,内部负责调用和返回结果类型。用户可以自定义实现CallAdapter

定义一个CustomRetrofit

public class CustomRetrofit {
 
// 存储各种自定义的CallAdapter 
private List<CustomCallAdapter> mCallAdaters; 
private CustomRetrofit() {
 
mCallAdaters = new ArrayList<>(); 
} 
private <T, R> void addCalladapter(CustomCallAdapter<T, R> callAdapter) {
 
mCallAdaters.add(callAdapter); 
} 
public <T> T create(Class<T> cls) {
 
return (T) Proxy.newProxyInstance(cls.getClassLoader(), new Class[]{
cls}, 
new InvocationHandler() {
 
@Override 
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
return convert(method); 
} 
}); 
} 
// 真正的执行 
private Object convert(Method method) {
 
Type type = method.getReturnType(); 
// 根据需要的返回类型找出CallAdapter 
CustomCallAdapter callAdapter = getCallAdapter(type); 
if (callAdapter == null) {
 
throw new RuntimeException("no callAdapter"); 
} 
// 解析参数 
CustomParam param = method.getAnnotation(CustomParam.class); 
int value = param == null ? 0 : param.value(); 
// callAdatper执行(忽略了最后结果转换这一步) 
return callAdapter.adapt(value); 
} 
private CustomCallAdapter getCallAdapter(Type type) {
 
for (CustomCallAdapter item : mCallAdaters) {
 
if (type == item.getResponseType()) {
 
return item; 
} 
} 
return null; 
} 
// 简单的builder模式 
public static class Builder {
 
private CustomRetrofit instance = null; 
public Builder() {
 
instance = new CustomRetrofit(); 
} 
public Builder addCallAdapter(CustomCallAdapter callAdapter) {
 
instance.addCalladapter(callAdapter); 
return this; 
} 
CustomRetrofit build() {
 
return instance; 
} 
} 
} 

上面的注解很简单和清晰了,不做过多解释。

使用

public interface SimpleApi {
 
@CustomParam(2) 
Integer test(); 
} 
public class SimpleCallAdapter extends CustomCallAdapter<Integer, Integer> {
 
@Override 
public Integer adapt(Integer param) {
 
return param; 
} 
@Override 
public Type getResponseType() {
 
return Integer.class; 
} 
} 

测试一下

    @Test 
public void testRetrofit() {
 
CustomRetrofit retrofit = new CustomRetrofit.Builder() 
.addCallAdapter(new SimpleCallAdapter()) 
.build(); 
int result = retrofit.create(SimpleApi.class).test(); 
System.out.println(result); 
} 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/6261.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论