【Android】retrofit源码浅析

417 阅读6分钟

一. 代理

代理这个词很好理解,就像我们耳熟能详的代购一样,我们不直接和商家去购买商品,而是通过中间商帮我们去买,这里的中间商就类似于代理的角色,当然中间商肯定是要赚差价的,哈哈,java中的代理根据创建时机以及方式的不同,可以分为两种:静态代理和动态代理。

1.静态代理

静态代理在使用时,被代理对象和代理对象需要有共同的父类或者实现同一接口,举个栗子,随便创建个类,作为我们所说的被代理对象,创建一个专门用于打印的接口PrintInfoIter,然后如上所述,创建Student类实现它:

interface PrintInfoIter {
    fun printInfo()
}

class Student :PrintInfoIter{
    override fun printInfo(){
        Log.e("proxy","----printInfo")
    }
}

然后创建代理对象类,同样需要实现PrintInfoIter接口,如下:

class StudentImpProxy(var infoIter: PrintInfoIter) : PrintInfoIter {
    private var printInfoIter: PrintInfoIter? = null

    init {
        this.printInfoIter = infoIter
    }

    override fun printInfo() {
        printInfoIter?.let {
            Log.e("proxy", "--------调用printInfo之前")
            it.printInfo()
            Log.e("proxy", "--------调用printInfo之后")
        }
    }
}

使用方式如下:

//静态代理
val studentImpProxy = StudentImpProxy(Student())
studentImpProxy.printInfo()

结果:

1.png

静态代理的作用就是在不修改被代理类代码的前提下,对功能进行扩展,缺点也很明显,需要代理类和被代理类都有共同的父类或者实现同一接口,之所以成为静态,个人理解是代码在程序运行之前已经编写完成,非动态生成实现代理功能。

2.动态代理

动态代理主要依赖ProxyInvocationHandler来完成代理工作,通过Proxy的newProxyInstance方法来创建代理类:

//loader:类加载器
//interfaces:对象实现的所有接口数组
//h:InvocationHandler对象实例
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

如何使用呢?还是上面的栗子,看看使用动态代理的方式如何使用:

/**
 * 动态代理类
 */
class StudentProxy : InvocationHandler {

    var obj: Any? = null

    fun newProxyInstance(obj: Any?): Any {
        this.obj = obj
        return Proxy.newProxyInstance(obj!!.javaClass.classLoader, obj.javaClass.interfaces, this)
    }

    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
        var result: Any? = null
        Log.e("proxy","--------调用${method}之前")

        var argsTemp: Array<out Any>? = arrayOf()
        args?.let {
            if(args.isNotEmpty())
                argsTemp = args
        }
        result = if(!argsTemp.isNullOrEmpty()){
            method?.invoke(obj,argsTemp)
        }else{
            method?.invoke(obj )
        }
        Log.e("proxy","--------调用${method}之后")
        return result ?: Any()
    }
}

使用:

//动态代理
val studentProxy = StudentProxy()
val printInfoIter = studentProxy.newProxyInstance(Student()) as PrintInfoIter
printInfoIter.printInfo()

结果:

2.png

可以发现,动态代理不需要与被代理对象一样,实现相同接口或者共同父类,相对来说比较灵活,但它同样是基于接口进行代理,另外JDK动态代理是Java原生支持的,不需要任何外部依赖。

二.Retrofit

Retrofit作为现在android开发的主流网络框架,或者说是一个封装了网络请求各个环节的库,因为其底层依然是使用的okhttp来发送网络请求,下面我们跟随源码来体验下其请求流程。

1.retrofit.create

我们在使用Retrofit进行网络请求的时候,通常会需要一个配置接口参数的类,包看请求类型,参数,header等等,然后通过retrofit.create获取该类实例,形如:

val apiService = retrofit.create(apiClass)

我们来看下retrofit.create具体干了啥:

public <T> T create(final Class<T> service) {
    validateServiceInterface(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);
          }
        });
  }

Proxy.newProxyInstance是不是很熟悉,上面刚介绍过,这边创建service类采用的就是动态代理的方式,主要代码就是loadServiceMethod(method).invoke,loadServiceMethod是解析请求各种参数的类,下面我们具体来看下。

2.ServiceMethod

loadServiceMethodServiceMethod类型,代码如下:

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是一个抽象类,具体实现类是HttpServiceMethod,来看下它的parseAnnotations方法:

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;
        //Kotlin suspend的处理
        if (isKotlinSuspendFunction) {
            Type[] parameterTypes = method.getGenericParameterTypes();
            Type responseType = Utils.getParameterLowerBound(0,
                    (ParameterizedType) parameterTypes[parameterTypes.length - 1]);

            adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
            annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
        } else {
            adapterType = method.getGenericReturnType();
        }

        //根据设置的addCallAdapterFactory类型,创建不同的callAdapter
        CallAdapter<ResponseT, ReturnT> callAdapter =
                createCallAdapter(retrofit, method, adapterType, annotations);
        Type responseType = callAdapter.responseType();

        //根据设置的addConverterFactory类型,创建不同的response转换器,用于把返回值装换为具体的实体类
        Converter<ResponseBody, ResponseT> responseConverter =
                createResponseConverter(retrofit, method, responseType);

        okhttp3.Call.Factory callFactory = retrofit.callFactory;
        //不同情况创建不同的HttpServiceMethod
        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);
        }
    }

这里创建了callAdapter对象,通过calladapter转换器,将okhttp3.call转换成可以用于发起网络请求的retrofit2.Call或者说用于rxjavaObservable对象,calladapter对象可以通过addCallAdapterFactory方法设置,不设置则使用系统默认的DefaultCallAdapterFactory,比如我们如果使用rxjava,通常会设置了RxJava2CallAdapter,来看下RxJava2CallAdapter的代码:

//这里只贴出关键代码
    final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
        private final Type responseType;
        private final @Nullable Scheduler scheduler;
        private final boolean isAsync;
        private final boolean isResult;
        private final boolean isBody;
        private final boolean isFlowable;
        private final boolean isSingle;
        private final boolean isMaybe;
        private final boolean isCompletable;

        RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,
                           boolean isResult, boolean isBody, boolean isFlowable, boolean isSingle, boolean isMaybe,
                           boolean isCompletable) {
            this.responseType = responseType;
            this.scheduler = scheduler;
            ......
        }

        @Override public Type responseType() {
            return responseType;
        }

        @Override public Object adapt(Call<R> call) {
            //这里是发送网络请求的入口
            Observable<Response<R>> responseObservable = isAsync
                    ? new CallEnqueueObservable<>(call)
                    : new CallExecuteObservable<>(call);

            Observable<?> observable;
            if (isResult) {
                observable = new ResultObservable<>(responseObservable);
            } else if (isBody) {
                observable = new BodyObservable<>(responseObservable);
            } else {
                observable = responseObservable;
            }
            return RxJavaPlugins.onAssembly(observable);
        }
    }

可以看到RxJava2CallAdapter实现了Retrofit的CallAdapter接口,adapt方法中看到了两个熟悉的类CallEnqueueObservable和CallExecuteObservable,异步和同步网络请求的类,CallEnqueueObservable代码:

//只贴关键代码
    final class CallEnqueueObservable<T> extends Observable<Response<T>> {
        private final Call<T> originalCall;

        CallEnqueueObservable(Call<T> originalCall) {
            this.originalCall = originalCall;
        }

        @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
            // Since Call is a one-shot type, clone it for each new observer.
            Call<T> call = originalCall.clone();
            CallCallback<T> callback = new CallCallback<>(call, observer);
            observer.onSubscribe(callback);
            if (!callback.isDisposed()) {
                //发送网络请求
                call.enqueue(callback);
            }
        }

        private static final class CallCallback<T> implements Disposable, Callback<T> {
            private final Call<?> call;
            private final Observer<? super Response<T>> observer;
            private volatile boolean disposed;
            boolean terminated = false;

            CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
                this.call = call;
                this.observer = observer;
            }

            @Override public void onResponse(Call<T> call, Response<T> response) {
                if (disposed) return;

                try {
                    observer.onNext(response);

                    if (!disposed) {
                        terminated = true;
                        observer.onComplete();
                    }
                } catch (Throwable t) {
                }
            }

            @Override public void onFailure(Call<T> call, Throwable t) {
            }

            @Override public void dispose() {
                call.cancel();
            }
        }
    }

这里通过call.enqueue发送网络请求,call其实就是HttpServiceMethod类中invoke方法中所创建的OkHttpCallOkHttpCall是对okhttp网络请求的封装,也是Retrofit中具体发送网络请求的类:

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

3.OkHttpCall

OkHttpCallretrofit库对okhttp网络请求的封装,可以简单看下OkHttpCall中的方法,发现都是okhttp中耳熟能详的内容,比如enqueue,execute等:

3.png

网络请求流程:在调用apiService方法时,Retrofit的create()通过动态代理生成一个代理类对象,也就是通过Proxy.newProxyInstance()来创建的代理对象,接下来使用ServiceMethod类解析各种注解,封装请求,之后调用invoke()方法,创建用于发送网络请求的okhttpcall类,最终返回用于发起网络请求的Call对象或者用于结合rxjava使用的Observable对象。

简单来讲,其实retrofit网络框架就是对okhttp网络框架的封装,可以更加方便的发起网络请求,简单几步即可完成,另外可以比较好的搭配rxjava或者kotlin协程,使得网络请求变得方便快捷,至此,本文所要介绍的内容已接近尾声,如果对你有任何帮助,点赞支持下我会非常开心!