Retrofit2 源码阅读

使用Retrofit作为Android网络请求已经非常普遍了,并且Retrofit的源码不仅少而且还很精妙,作为阅读学习的对象在合适不过了。虽然很久之前就用了,但是还真没看过源码,趁着最近空闲就试着看看把。本文Retrofit版本是 2.6.0。看完我觉得还是2.4之前会更轻松点吧,可惜我没找到老版本的jar包

基本用法

要了解一个框架的源码,肯定要知道它的基本用法。然后从基本用法里选择一个入口方法,这样就可以跟着用法读下去了。

1、定义请求接口
public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<UserBean>> listRepos(@Path("user") String user);
}
2、初始化Retrofit
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .client(new OkHttpClient())
            //.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    GitHubService service = retrofit.create(GitHubService.class);
3、网络请求
    Call<List<UserBean>> repos = service.listRepos("octocat");
    {
        repos.enqueue(new Callback<List<UserBean>>() {
            @Override
            public void onResponse(Call<List<UserBean>> call, Response<List<UserBean>> response) {
                List<UserBean> list = response.body();
            }

            @Override
            public void onFailure(Call<List<UserBean>> call, Throwable throwable) {

            }
        });
    }

源码阅读

从上面3个使用步骤我们可以很明显的看出retrofit.create()是一个入口方法,首先先来看看Retrofit()中都初始化了啥。

一、Retrofit初始化

Retrofit通过Builder设计模式进行初始化。看一下build()方法中都做了些什么。

public Retrofit build() {
	//初始化时baseUrl是必须的
    if(this.baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    } else {
        Object callFactory = this.callFactory;
        //初始化时如果没有设置client,callFactory 为null
        //默认创建一个OkHttpClient赋值给callFactory 
        if(callFactory == null) {
            callFactory = new OkHttpClient();
        }
        Executor callbackExecutor = this.callbackExecutor;
        if(callbackExecutor == null) {
            callbackExecutor = this.platform.defaultCallbackExecutor();
        }
  		//调用addCallAdapterFactory时初始化
  		//如果没有初始化,使用DefaultCallAdapterFactory
        ArrayList callAdapterFactories = new ArrayList(this.callAdapterFactories);
        callAdapterFactories.addAll(this.platform.defaultCallAdapterFactories(callbackExecutor));
        //调用addConverterFactory时候初始化,
        //如果没有初始化使用默认的BuiltInConverters
        ArrayList converterFactories = new ArrayList(1 + this.converterFactories.size() + this.platform.defaultConverterFactoriesSize());
        converterFactories.add(new BuiltInConverters());
        converterFactories.addAll(this.converterFactories);
        converterFactories.addAll(this.platform.defaultConverterFactories());
        return new Retrofit((Factory)callFactory, this.baseUrl, Collections.unmodifiableList(converterFactories), Collections.unmodifiableList(callAdapterFactories), callbackExecutor, this.validateEagerly);
    }
}

构造Retrofit对象的时候初始化了三个非常重要的参数:

  • callFactory
  • CallAdapter
  • ConverterFactory

1、callFactory ,即OkHttpClient,继承Call.Factory。OKhttp的工厂类
2、CallAdapter。适配器模式,负责将Call对象转换成我们需要的类型。例如Rxjava中的Observable对象。

如下默认login返回Call对象,当时用初始化时调用addCallAdapterFactory(RxJava2CallAdapterFactory.create())给Retrofit添加一个RxJava的适配器的时候,则返回Observable对象

    // 使用默认适配器时
    Call<String> login();  

    // 添加Rxjava适配器时的返回
    Observable<String> login();  

3、ConverterFactory,转换工厂。将http返回的response转换成我们需要的对象。如UserBean。

二、构建service对象
 GitHubService service = retrofit.create(GitHubService.class);

create方法源码如下:

    public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);
        if(this.validateEagerly) {
            this.eagerlyValidateMethods(service);
        }

        return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
            private final Platform platform = Platform.get();
            private final Object[] emptyArgs = new Object[0];

            @Nullable
            public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
                return method.getDeclaringClass() == Object.class?method.invoke(this, args):(this.platform.isDefaultMethod(method)?
				this.platform.invokeDefaultMethod(method, service, proxy, args):
				Retrofit.this.loadServiceMethod(method).invoke(args != null?args:this.emptyArgs));
            }
        });
    }

Create方法中完成了两件事情:

1、使用代理模式动态创建一个Service对象并返回

2、创建ServiceMethod对象,并且调用invoke()方法。

关于动态代理和反射可以我的另外两篇文章:
代理模式
Java反射机制

创建ServiceMethod对象

通过loadServiceMethod()方法获得一个ServiceMethod。

    ServiceMethod<?> loadServiceMethod(Method method) {
        ServiceMethod result = (ServiceMethod)this.serviceMethodCache.get(method);
        if(result != null) {
            return result;
        } else {
            Map var3 = this.serviceMethodCache;
            synchronized(this.serviceMethodCache) {
                result = (ServiceMethod)this.serviceMethodCache.get(method);
                if(result == null) {
                    result = ServiceMethod.parseAnnotations(this, method);
                    this.serviceMethodCache.put(method, result);
                }
                return result;
            }
        }
    }

可以看到loadServiceMethod()方法中有个会对ServiceMethod对象进行缓存,当ServiceMethod对象为null时,会调用ServiceMethod.parseAnnotations(this, method)获得一个ServiceMethod对象。

abstract class ServiceMethod<T> {
    ServiceMethod() {
    }

    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
        Type returnType = method.getGenericReturnType();
        if(Utils.hasUnresolvableType(returnType)) {
            throw Utils.methodError(method, "Method return type must not include a type variable or wildcard: %s", new Object[]{returnType});
        } else if(returnType == Void.TYPE) {
            throw Utils.methodError(method, "Service methods cannot return void.", new Object[0]);
        } else {
            return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
        }
    }

    @Nullable
    abstract T invoke(Object[] var1);
}

从上面源码可以看出ServiceMethod是一个抽象类。通过parseAnnotations()方法获得一个ServiceMethod对象。

获得RequestFactory

看一下ServiceMethod.parseAnnotations方法,首先会调用RequestFactory.parseAnnotations方法,获得一个RequestFactory 对象

  RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

那么RequestFactory 又是什么呢?

查看RequestFactory.parseAnnotations源码如下

在这里插入图片描述

可以看到RequestFactory又是一个Builder模式。看一下Builder中的参数和方法
在这里插入图片描述
从上面的参数不难看出,这其实就是我们基本用法第一步中新建GitHubService 中的请求方法的解析。


    @GET("users/{user}/repos")
    Call<List<UserBean>> listRepos(@Path("user") String user);

比如解析上面的请求方法GET,路径"users/{user}/repos",参数等等。

下面来看一下有哪些解析方法:

//解析Http请求的方法,get、post等
private void parseMethodAnnotation(Annotation annotation);
//解析Http请求的方法和路径
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody);
//解析请求头
private Headers parseHeaders(String[] headers)
//解析请求参数
private ParameterHandler<?> parseParameter(int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation)
//解析参数中的注解 例如@path。方法内调用ParameterHandler解析
 private ParameterHandler<?> parseParameterAnnotation(int p, Type type, Annotation[] annotations, Annotation annotation)
 
static Set<String> parsePathParameters(String path);

解析方法时有个非常重要的类ParameterHandler,具体的解析是由ParameterHandler来完成的。

现在我们已经知道了RequestFactory的作用了,解析http请求的方法,路径,请求头等和http请求相关的参数了。

继续回到我们的ServiceMethod类中。

    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
        Type returnType = method.getGenericReturnType();
        if(Utils.hasUnresolvableType(returnType)) {
            throw Utils.methodError(method, "Method return type must not include a type variable or wildcard: %s", new Object[]{returnType});
        } else if(returnType == Void.TYPE) {
            throw Utils.methodError(method, "Service methods cannot return void.", new Object[0]);
        } else {
            return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
        }
    }

通过反射获得方法的返回类型:
Type returnType = method.getGenericReturnType();

然后调用HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);获得一个HttpServiceMethod对象。

HttpServiceMethod

HttpServiceMethod继承自ServiceMethod。

HttpServiceMethod构造方法如下:

    HttpServiceMethod(RequestFactory requestFactory, Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter) {
        this.requestFactory = requestFactory;
        this.callFactory = callFactory;
        this.responseConverter = responseConverter;
    }

需要初始化三个非常重要的参数:

  • requestFactory :service中的请求参数
  • callFactory :Call的适配器
  • responseConverter :response转换器

HttpServiceMethod.parseAnnotations()源码如下(有省略):

    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {
		...
        Annotation[] annotations = method.getAnnotations();
        Object adapterType;
        Type responseType;
		...
        adapterType = method.getGenericReturnType(); 
		//创建一个Call适配器
        CallAdapter callAdapter1 = createCallAdapter(retrofit, method, (Type)adapterType, annotations);
        //获得返回类型
        responseType = callAdapter1.responseType();
		...
		//创建一个Converter
        Converter responseConverter = createResponseConverter(retrofit, method, responseType);
        Factory callFactory = retrofit.callFactory;
        return (HttpServiceMethod)(new HttpServiceMethod.CallAdapted(requestFactory, callFactory, responseConverter, callAdapter1);
	}

1、创建CallAdapter 对象

跟踪createCallAdapter()方法,最终会调用Retrofit类中的nextCallAdapter()方法。源码如下

    public CallAdapter<?, ?> nextCallAdapter(@Nullable retrofit2.CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
        Utils.checkNotNull(returnType, "returnType == null");
        Utils.checkNotNull(annotations, "annotations == null");
        int start = this.callAdapterFactories.indexOf(skipPast) + 1;
        int builder = start;

        int i;
        for(i = this.callAdapterFactories.size(); builder < i; ++builder) {
            CallAdapter count = ((retrofit2.CallAdapter.Factory)this.callAdapterFactories.get(builder)).get(returnType, annotations, this);
            //获得一个不为null的CallAdapter 并且返回
            if(count != null) {
                return count;
            }
        }
		...
        throw new IllegalArgumentException(var8.toString());
    }

nextCallAdapter()方法中遍历callAdapterFactories集合中的CallAdapter,而callAdapterFactories则在Retrofit初始化的时候通过addCallAdapterFactory()赋值或者默认值。

当获得一个不为null的CallAdapter 的时候则返回。

2、创建Converter对象

通过responseType = callAdapter1.responseType();得到response类型。

通过Converter responseConverter = createResponseConverter(retrofit, method, responseType);创建一个responseConverter

跟踪createResponseConverter()方法,最终在Retrofit中调用nextResponseBodyConverter()方法,源码如下:

	public <T> Converter<ResponseBody, T> nextResponseBodyConverter(@Nullable retrofit2.Converter.Factory skipPast, Type type, Annotation[] annotations) {
        Utils.checkNotNull(type, "type == null");
        Utils.checkNotNull(annotations, "annotations == null");
        int start = this.converterFactories.indexOf(skipPast) + 1;
        int builder = start;

        int i;
        for(i = this.converterFactories.size(); builder < i; ++builder) {
            Converter count = ((retrofit2.Converter.Factory)this.converterFactories.get(builder)).responseBodyConverter(type, annotations, this);
            if(count != null) {
                return count;
            }
        }

        throw new IllegalArgumentException(var8.toString());
    }

同样获得Retrofit初始化时Converter 对象并返回。通过addConverterFactory()方法初始化或者使用默认的Converter 。

3、获得callFactory

通过Factory callFactory = retrofit.callFactory;获得一个Factory 对象。

同样是在retrofit初始化的时候创建赋值。

4、返回HttpServiceMethod对象

new一个继承自HttpServiceMethod 的 CallAdapted对象

    static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
        private final CallAdapter<ResponseT, ReturnT> callAdapter;

        CallAdapted(RequestFactory requestFactory, Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter, CallAdapter<ResponseT, ReturnT> callAdapter) {
            super(requestFactory, callFactory, responseConverter);
            this.callAdapter = callAdapter;
        }

        protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
            return this.callAdapter.adapt(call);
        }
    }

以上就是HttpServiceMethod类中的主要作用,到此ServiceMethod创建,我们需要再次回到Create()方法中。

创建OkHttpCall 对象

Create方法中完成了两件事情:

1、使用代理模式动态创建一个Service对象并返回

2、创建ServiceMethod对象,并且调用invoke()方法。

上面ServiceMethod对象创建完毕,我们已经获得一个ServiceMethod的实例对象HttpServiceMethod,现在执行HttpServiceMethod对象中的invoke()方法。

源码如下:

    final ReturnT invoke(Object[] args) {
        OkHttpCall call = new OkHttpCall(this.requestFactory, args, this.callFactory, this.responseConverter);
        return this.adapt(call, args);
    }

在invoke方法中会创建并初始化一个OkHttpCall 对象,继承Call对象。

三、请求网络
    Call<List<UserBean>> call = service.listRepos("octocat");
    {
        call.enqueue(new Callback<List<UserBean>>() {
            @Override
            public void onResponse(Call<List<UserBean>> call, Response<List<UserBean>> response) {
            }

            @Override
            public void onFailure(Call<List<UserBean>> call, Throwable throwable) {
            }
        });
    }
1、call.queue()源码

调用ApiService中的请求方法,获得一个Call返回值,通过call.enqueue()执行网络请求。

Call对象是一个接口,它的实现类是OkHttpCall ,所以真正网络请求逻辑都在OkHttpCall 中

queue()方法源码如下:

    public void enqueue(final Callback<T> callback) {

        okhttp3.Call call;//声明一个okhttp请求call
        Throwable failure;
        	
        	...//省略一些空判断,空处理
        	
        	//执行okhttp请求,Retrofit是基于okhttp3进行封装的网络请求框架,
        	//真正请求网络的部分还是OKhttp
            call.enqueue(new okhttp3.Callback() {
            	//okhttp成功回调
                public void onResponse(okhttp3.Call call, Response rawResponse) {
                    retrofit2.Response response;
                    try {
                    	//解析成功的数据,返回我们需要的类型
                        response = OkHttpCall.this.parseResponse(rawResponse);
                    } catch (Throwable var6) {
                        Utils.throwIfFatal(var6);
                        this.callFailure(var6);
                        return;
                    }

                    try {
                    	//外部callback回调
                        callback.onResponse(OkHttpCall.this, response);
                    } catch (Throwable var5) {
                        Utils.throwIfFatal(var5);
                        var5.printStackTrace();
                    }
                }
				//OKhttp失败回调
                public void onFailure(okhttp3.Call call, IOException e) {
                    this.callFailure(e);
                }				
                private void callFailure(Throwable e) {
                    try {
                    	//外部Callback回调
                        callback.onFailure(OkHttpCall.this, e);
                    } catch (Throwable var3) {
                        Utils.throwIfFatal(var3);
                        var3.printStackTrace();
                    }
                }
            });

    }

从源码可以看到,真正执行网络请求的是OKhttp,而当请求成功的时候,okhttp成功回调中有一行很重要的代码:

 retrofit2.Response response;
 //解析OKhttp返回的rawResponse,转换成我们需要的response
 response = OkHttpCall.this.parseResponse(rawResponse);
解析OKhttp成功返回结果

parseResponse()源码如下:

    retrofit2.Response<T> parseResponse(Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
        rawResponse = rawResponse.newBuilder().body(new OkHttpCall.NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();
        int code = rawResponse.code();
        if(code >= 200 && code < 300) {
            if(code != 204 && code != 205) {
                OkHttpCall.ExceptionCatchingResponseBody catchingBody1 = new OkHttpCall.ExceptionCatchingResponseBody(rawBody);

                try {
                	//将Body数据转换成我们需要的类型
                    Object e1 = this.responseConverter.convert(catchingBody1);
                    return retrofit2.Response.success(e1, rawResponse);
                } catch (RuntimeException var9) {
                    catchingBody1.throwIfCaught();
                    throw var9;
                }
            } else {
                rawBody.close();
                return retrofit2.Response.success((Object)null, rawResponse);
            }
        } else {
          	...//省略
            return e;
        }
    }

这里面也有段非常核心的代码:

  Object e1 = this.responseConverter.convert(catchingBody1);

通过 responseConverter 调用 convert 方法实现类型转换。

那么responseConverter 是啥?

在这里插入图片描述
responseConverter 是一个Converter对象,负责将ResponseBody 转换成 T 类型。

responseConverter 在哪赋值?
再来看一下
可以看到responseConverter 是在OKhttpCall的构造方法中进行初始化的

OKhttpCall的创建是在调用HttpServiceMethod 的 invoke() 方法中进行创建的,而responseConverter就是在HttpServiceMethod 中通过Converter responseConverter = createResponseConverter(retrofit, method, responseType);进行创建的。

到此从Retrofit初始化到网络结束已经完成。
因为在Retrofit初始化的时候,初始化了一个 defaultCallbackExecutor。

                Executor callbackExecutor = this.callbackExecutor;
                if(callbackExecutor == null) {
                    callbackExecutor = this.platform.defaultCallbackExecutor();
                }

而defaultCallbackExecutor 在Android平台源码如下

        public Executor defaultCallbackExecutor() {
            return new Platform.Android.MainThreadExecutor();
        }
        
        static class MainThreadExecutor implements Executor {
            private final Handler handler = new Handler(Looper.getMainLooper());

            MainThreadExecutor() {
            }

            public void execute(Runnable r) {
                this.handler.post(r);
            }
        }

可以看到这是一个在主线程的回调,所以我们可以直接在Retrofit的callback中进行进行ui操作。

Retrofit流程图:

在这里插入图片描述

总结

Retrofit源码阅读到这里了,其实还有不少为什么这样做的问题还没有消化,现在只是知道是这样做这样写的。看之前也是做了些准备的,比如去学习了代理模式,反射,适配器模式,装饰模式等。还好也没准备一口气吃个胖子,慢慢积累,过段时间再来看看会不会好点。

发布了82 篇原创文章 · 获赞 16 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/sjdjdjdjahd/article/details/99298089