Retrofit源码解析

Retrofit的简单使用

1. 添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
2. 创建一个interface作为Web Service的请求集合,在上面用注解写入需要配置的请求方法
interface GithubService {
    @GET("/users/{user}/repos")
    fun listRepos(@Path("user") user: String): Call>
}
3. 获取Retrofit实例(单例对象)
object Net {
    fun instance() =
        Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl("https://api.github.com/")
            .build()
}
4. 创建出Service interface实例,调用对应的接口方法,创建出相应的可以用来发起网络请求的Call对象
val githubService = Net.instance().create(GithubService::class.java)
val listRepos = githubService.listRepos("hsicen")
5. 使用Call.execute()或者Call.enqueue()发起请求
listRepos.enqueue(object : Callback> {
    override fun onFailure(call: Call>, t: Throwable) {
        tv_content.text = t.message
    }
    override fun onResponse(call: Call>, response: Response>) {
        tv_content.text = response.body().toString()
    }
})

Retrofit源码分析

首先我们从离我们最近的位置作为切入点(通常是业务代码的最后一行),这里我们点进Call.enqueue(),看看里面的代码逻辑

/**
  * Asynchronously send the request and notify {@code callback} of its response or if an error
  * occurred talking to the server, creating the request, or processing the response.
  */
void enqueue(Callback callback);

发现这是一个接口,没有具体实现,切入失败;现在需要逐步回退寻找到下一个切入点Retrofit.create()

public  T create(final Class service) {
    Utils.validateServiceInterface(service);  //接口验证
    if (validateEagerly) {eagerlyValidateMethods(service);}  //提前验证所有方法的正确性,会用到反射
    //动态代理  创建一个运行时的类,Interface的每一个方法调用都会交由InvocationHandler来处理
    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) {//继承自Object的方法
                return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {  //接口默认方法 Java8
                return platform.invokeDefaultMethod(method, service, proxy, args);
            }

            //关键代码
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
        }
    });
}

可以看到前面两行是代码健壮性验证,核心代码Proxy.newProxyInstance()方法来创建Service实例。这个方法会为参数中的Interface创建一个对象,这个对象实现了Interface的每个方法,并且每个方法的实现都会雷同的:调用对象实例内部的一个InvocationHandler成员变量的invoke方法,并把自己的方法信息传递进去。这样就在实质上实现了代理逻辑;Interface中的方法全部由一个另外设定的InvocationHandler对象来进行代理操作。并且这些方法的具体实现是在运行时生成Interface实例时才确定的,而不是在编译时。这就是动态代理机制,大致像下面这样:

//GithubService.kt
interface GithubService {
    @GET("/users/{user}/repos")
    fun listRepos(@Path("user") user: String): Call>

    @GET("/users/hsicen")
    fun getUser(): Call
}

//realService
class RealService : GithubService {
    private val invocationHandler = object : InvocationHandler {
        private val platform = Platform.get();

        override fun invoke(proxy: Any?, method: Method?, args: Array?): Any {
            //扮演代理角色,对不同的方法做不同的处理

            return Any()
        }
    }

    override fun listRepos(user: String): Call> {
        val method = GithubService::class.java.getMethod("listRepos")
        return invocationHandler.invoke(this, method, null) as Call>
    }

    override fun getUser(): Call {
        val method = GithubService::class.java.getMethod("getUser")
        return invocationHandler.invoke(this, method, null) as Call
    }
}

接下主要关注loadServiceMethod(method).invoke(args != null ? args : emptyArgs)这句代码,loadServiceMethod()invoke()是这个方法中关键作用的代码;invoke()就是Retrofit创建Service实例的关键

abstract @Nullable T invoke(Object[] args);

点进去发现,这是ServiceMethod的抽象方法;那么只好看看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.parseAnnotations()方法

static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(method,"Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
        throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

在这个方法中主要看HttpServiceMethod.parseAnnotations(),这个方法的代码就比较多了,我们主要看返回处的代码

if (!isKotlinSuspendFunction) {
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod) new SuspendForResponse<>(requestFactory,callFactory, responseConverter, (CallAdapter>) callAdapter);
} else {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod) new SuspendForBody<>(requestFactory,callFactory, responseConverter, (CallAdapter>) callAdapter,continuationBodyNullable);
}

HttpServiceMethodServiceMethod的子类,而HttpServiceMethod.parseAnnotations()是返回ServiceMethod对象,然后再执行ServiceMethod的invoke方法,这里我们可以直接查看HttpServiceMethod的invoke方法

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

在invoke()中创建了一个OkHttpCall,然后调用了adapt()方法,返回我们需要的对象,那么我们就来看这个adapt()方法干了什么,继续点进去

protected abstract @Nullable ReturnT adapt(Call call, Object[] args);

又是一个抽象方法,看来直接查看adapt()方法行不通,那么就只好看看OkHttpCall做了什么了,我们点进OkHttpCall看一下吧

final class OkHttpCall implements Call {
   .......
}

OkHttpCall是继承自Retrofit的Call的,也就是我们第一步没走通的那个Call(因为Call的enqueue方法是抽象的),那么它有没有实现Call的enqueue()方法呢?

@Override public void enqueue(final Callback callback) {
    okhttp3.Call call;
    synchronized (this) {
        call = rawCall;
        if (call == null && failure == null) {
            call = rawCall = createRawCall();
        }
    }

    call.enqueue(new okhttp3.Callback() {
        @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response response = parseResponse(rawResponse);
            callback.onResponse(OkHttpCall.this, response);
        }

        @Override public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
        }
    });
}

由于enqueue()中代码量较大,我精简了这部分代码,enqueue()主要的工作是创建了一个okhttp3的Call,然后调用这个call的enqueue()方法去发起网络请求,然后将回调结果预处理之后,交由Retrofit的Callback

因此,到这里我们对Retrofit的工作流程就有了一个大致的了解,Retrofit通过动态代理创建出Service实例,然后通过这个实例调用对应的api得到一个Retrofit的Call对象,这个Call对象又创建了一个OkHttp3的Call实例去发起网络请求,然后将结果回调给Retrofit的Callback

在上面的分析过程中,有一个点还没有解决,那就是我们在创建出OkHttpCall对象后,然后调用了adapt()方法,这个adapt()方法是干什么用的呢?做了哪些处理?

在工作中我们知道,adapter是适配器的意思,作为中间桥梁的作用;猜测是不是对OkHttpCall的转换处理呢?因为我们知道Retrofit可以和RxJava结合使用,是不是就是因为这个adapt()的作用呢?当然,我们还需要查看源码,才能找到答案

找到刚才那个抽象的adapt()方法,查看其实现的地方,我们会看到HttpServiceMethod内部有一个静态内部类实现了该抽象方法

static final class CallAdapted extends HttpServiceMethod {
    private final CallAdapter callAdapter;

    CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,Converter responseConverter,CallAdapter callAdapter) {
        super(requestFactory, callFactory, responseConverter);
        this.callAdapter = callAdapter;
    }

    @Override protected ReturnT adapt(Call call, Object[] args) {
        return callAdapter.adapt(call);
    }
}

在这个类中,创建了一个CallAdapter类,并将adapt()交由CallAdapter的adapt()来实现,这时候我们可以联想到在Retrofit初始化的时候,有这么一句代码 addCallAdapterFactory(RxJava2CallAdapterFactory.create()),加上这句代码后,我们就可以将Call对象转化为Observable对象,和RxJava进行交互了,看来这个adapt()方法很可能就是将OkHttpCall进行转换的作用,为了验证我们的猜想,继续深入源码分析

这个静态内部类的callAdapter是构造方法传进来的,我们一步一步的向上找

CallAdapted -> callAdapter
HttpServiceMethod -> createCallAdapter()
Retrofit -> callAdapter()
Retrofit -> nextCallAdapter() callAdapterFactories.get()

最后我们发现CallAdapter来自callAdapterFactories变量,那么我们现在就需要找到callAdapterFactories的来源

// Make a defensive copy of the adapters and add the default Call adapter.
List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

我们可以发现这个callAdapterFactories分了两次添加,一次是callAdapterFactories变量,另一次是和平台相关的默认CallAdapterFactories,我们先看这个和平台相关默认的CallAdapterFactories,我们这里就只看Android平台

@Override List defaultCallAdapterFactories(@Nullable Executor callbackExecutor) {
    if (callbackExecutor == null) throw new AssertionError();
    DefaultCallAdapterFactory executorFactory = newDefaultCallAdapterFactory(callbackExecutor);
    return Build.VERSION.SDK_INT >= 24
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
}

首先声明了一个Executor,看命名,这个Executor是用于回调的;然后创建了DefaultCallAdapterFactory(),我们点进这个类,看它的get()方法做了什么操作

@Override public @Nullable CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    return new CallAdapter>() {
        @Override public Type responseType() {
            return responseType;
        }

        @Override public Call adapt(Call call) {
            return executor == null
                ? call
                : new ExecutorCallbackCall<>(executor, call);
        }
    };
}
 
 

我只截取了核心代码,我们可以看到在get()方法中返回了一个CallAdapter,还有一点应该注意,我们找这个CallAdapter的原因是什么,是不是要弄清楚它的adapt()方法做了什么,刚开始由于CallAdapter的adapt()是抽象方法,所以我们找到了现在这里;那么,现在我们可以看到DefaultCallAdapterFactory类的get()方法返回的是一个CallAdapter,在它的adapt()方法里返回了ExecutorCallbackCall对象,还记得OkHttpCall么?当时OkHttpCall是通过adapt(call)方法传进来的,DefaultCallAdapterFactory类里又原封不动的传给了ExecutorCallbackCall类,现在ExecutorCallbackCall对象做了什么处理

static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
        this.callbackExecutor = callbackExecutor;
        this.delegate = delegate;
    }

    @Override public void enqueue(final Callback callback) {
        delegate.enqueue(new Callback() {
            @Override public void onResponse(Call call, final Response response) {
                callbackExecutor.execute(new Runnable() {
                    @Override public void run() {
                        if (delegate.isCanceled()) {
                            // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                            callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                            callback.onResponse(ExecutorCallbackCall.this, response);
                        }
                    }
                });
            }

            @Override public void onFailure(Call call, final Throwable t) {
                callbackExecutor.execute(new Runnable() {
                    @Override public void run() {
                        callback.onFailure(ExecutorCallbackCall.this, t);
                    }
                });
            }
        });
    }
}

可以看到,ExecutorCallbackCall是DefaultCallAdapterFactory的静态内部类,继承自Retrofit的Call,与OkHttpCall是同类的,它的作用是把操作切回主线程后再交给Callback

分析完这个和平台相关的默认CallAdapter,我们再来看看callAdapterFactories变量中的CallAdapter,我们点击callAdapterFactories变量,看看哪里对它进行了添加操作

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
    callAdapterFactories.add(checkNotNull(factory, "factory == null"));
    return this;
}

fun instance(): Retrofit =
    Retrofit.Builder()
     .addConverterFactory(GsonConverterFactory.create())
     .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
     .baseUrl("https://api.github.com/")
     .build()

这些就明白了,这个CallAdapter是我们初始化Retrofit时我们主动添加进去的,我们这里添加的CallAdapterFactory是和RxJava结合使用的,像下面这样

//GithubService.kt
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String): Observable>

//发起网络请求
val repoService = Net.instance().create(GithubService::class.java)
repoService.listRepos("hsicen")
 .observeOn(Schedulers.newThread())
 .subscribe(object : Observer> {
    override fun onComplete() {

    }

    override fun onSubscribe(d: Disposable?) {

    }

    override fun onNext(value: List?) {

    }

    override fun onError(e: Throwable?) {

    }
 })

但是Observable回调的接口太多了,在App中更推荐使用Single

//GithubService.kt
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String): Observable>

//发起网络请求
val repoService = Net.instance().create(GithubService::class.java)
repoService.listRepos("hsicen")
    .observeOn(Schedulers.newThread())
    .subscribe(object : SingleObserver> {
        override fun onSubscribe(d: Disposable?) {

        }

        override fun onSuccess(value: List?) {

        }

        override fun onError(e: Throwable?) {

        }
    })

源码分析总结

  • 通过 Retrofit.create(Class) ⽅法创建出 Service interface 的实例,从⽽使得 Service 中配置的方法变得可用,这是 Retrofit 代码结构的核心

  • Retrofit.create() ⽅法内部,使⽤的是Proxy.newProxyInstance() ⽅法来创建Service实例。这个方法会为参数中的多 interface(具体到Retrofit来说,是固定传入⼀个interface)创建一个对象,这个对象实现了所有interface的每个方法,并且每个方法的实现都是雷同的:调⽤对象实例内部的一个InvocationHandler 成员变量的 invoke() ⽅法,并把⾃⼰的⽅法信息传递进去。这样就在实质上实现了代理逻辑:interface 中的⽅法全部由⼀个另外设定的InvocationHandler对象来进⾏代理操作。并且,这些⽅法的具体实现是在运行时⽣ interface实例时才确定的,⽽不是在编译时(虽然在编译时就已经可以通过代码逻辑推断出来)。这就是「动态代理理机制」的具体含义。

  • 因此,invoke() ⽅法中的逻辑,就是 Retrofit 创建 Service 实例的关键。这个⽅法内有三行关键代码,共同组成了具体逻辑:

    1. ServiceMethod 的创建 loadServiceMethod(method)
      这⾏代码负责读取 interface 中原方法的信息(包括返回值类型、⽅法注解、参数类型、参数注解),并将这些信息做初步分析。实际返回的是一个 HttpServiceMethod

    2. OkHttpCall 的创建 new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)
      OkHttpCall是retrofit2.Call 的子类。这行代码负责将ServiceMethod解读到的信息(主要是一个 RequestFactory 、一个 OkHttpClient 和⼀个 ResponseConverter )封装进 OkHttpCall ;而这个对象可以在需要的时候(例如它的 enqueue() ⽅法被调⽤的时候),利用RequestFactory和OkHttpClient来创建一个okhttp3.Call对象,并调⽤这个okhttp3.Call对象来进行⽹络请求的发起,然后利用ResponseConverter对结果进行预处理之后,交回给 Retrofit 的 Callback

    3. adapt()⽅法 return callAdapter.adapt(new OkHttpCall...)
      这个方法会使用一个CallAdapter对象来把OkHttpCall对象进行转换,⽣成⼀个新的对象。默认情况下,返回的是⼀个ExecutorCallbackCall,它的作用是把操作切回主线程后再交给Callback 。另外,如果有自定义的CallAdapter,这里也可以⽣成别的类型的对象,例例如 RxJava 的Observable ,来让 Retrofit 可以和 RxJava 结合使用。

Retrofit使用总结

1. 如果要直接获取网络返回的字符串,使用ResponseBody作为参数
@GET("sore")
Call  getLol();
2. 一个Call只能被执行一次,如果要多次执行Call对象,可以通过clone,来clone一份call,从新调用
Call newCall = mCall.clone()
3. 固定参数查询,不需要动态添加参数,直接调用查询
@GET("/some/endpoint?fixed=query")
Call someEndpoint();
apiService.someEndpoint();

GET  /some/endpoint?fixed=query  HTTP/1.1
4. 动态参数查询,每次网络请求查询指定参数的内容
@GET("/some/endpoint")
Call someEndpoint( @Query("dynamic") String dynamic);
apiService.someEndpoint("query");

GET  /some/endpoint?dynamic=query  HTTP/1.1
5. 动态Map参数查询
@GET("/some/endpoint")
Call someEndpoint(@QueryMap Map dynamic);
apiService.someEndpoint(Collections.singletonMap("dynamic", "query"));

GET  /some/endpoint?dynamic=query  HTTP/1.1
6. 省略动态参数查询
@GET("/some/endpoint")
Call someEndpoint(@Query("dynamic") String dynamic);
apiService.someEndpoint(null);

GET  /some/endpoint  HTTP/1.1
7. 固定+动态参数查询
@GET("/some/endpoint?fixed=query")
Call someEndpoint(@Query("dynamic") String dynamic);
apiService.someEndpoint("query");

GET  /some/endpoint?fixed=query&dynamic=query  HTTP/1.1
8. 路径替换查询
@GET("/some/endpoint/{thing}")
Call someEndpoint( @Path("thing") String thing);
apiService.someEndpoint("bar");

GET  /some/endpoint/bar  HTTP/1.1
8. 固定头查询
@GET("/some/endpoint")
@Headers("Accept-Encoding: application/json")
Call someEndpoint();
apiService.someEndpoint();

GET  /some/endpoint  HTTP/1.1
Accept-Encoding: application/json
9. 动态头查询
@GET("/some/endpoint")
Call someEndpoint(@Header("Location") String location);
apiService.someEndpoint("Droidcon NYC 2015");

GET  /some/endpoint  HTTP/1.1
Location: Droidcon NYC 2015
10. 固定+动态头查询
@GET("/some/endpoint")
@Headers("Accept-Encoding: application/json")
Call someEndpoint(@Header("Location") String location);
apiService.someEndpoint("Droidcon NYC 2015");

GET  /some/endpoint  HTTP/1.1
Accept-Encoding: application/json
Location: Droidcon NYC 2015
11. Post请求,无Body
@POST("/some/endpoint")
Call someEndpoint();
apiService.someEndpoint();

POST  /some/endpoint  HTTP/1.1
Content-Length: 0
12. Post请求有Body
@POST("/some/endpoint")
Call someEndpoint(@Body SomeRequest body);
apiService.someEndpoint();

POST  /some/endpoint  HTTP/1.1
Content-Length: 3
Content-Type: text/html

xdadasd
13. 表单编码字段
@FormUrlEncoded
@POST("/some/endpoint")
Call someEndpoint( @Field("name1") String name1, @Field("name2") String name2);
apiService.someEndpoint("value1", "value2");

POST /some/endpoint HTTP/1.1
Content-Length: 25
Content-Type: application/x-www-form-urlencoded

name1=value1&name2=value2
14. 表单编码字段(Map)
@FormUrlEncoded
@POST("/some/endpoint")
Call someEndpoint( @FieldMap Map names);
apiService.someEndpoint(ImmutableMap.of("name1", "value1", "name2", "value2"));

POST /some/endpoint HTTP/1.1
Content-Length: 25
Content-Type: application/x-www-form-urlencoded

name1=value1&name2=value2
15. 动态Url(Dynamic URL parameter)
@GET
Call> getActivityList(@Url String url,@QueryMap Map map);
Call> call = service.getActivityList("http://115.159.198.162:3001/api/ActivitySubjects", map);

你可能感兴趣的:(Retrofit源码解析)