0
点赞
收藏
分享

微信扫一扫

Retrofit 源码解析

关键类功能说明

Retrofit

Retrofit提供的子系统

  1. serviceMethodCache(自定义的接口映射对象集合) 2. baseUrl(请求地址)
  2. callFactory(默认为OKHttpCall)
  3. converterFactories(数据解析器工厂集合)
  4. callAdapterFactories(Call适配器工厂集合)
  5. callbackExecutor(回调执行,Android平台默认为MainThreadExecutor)

使用Builder模型构建(把对象依赖的零件创建、零件的组装封装起来;以使客户很方便的获取一个复杂
对象;)

Platform

Retrofit中用来管理多平台的方法,支持Android、Java8。通过findPlatform获取对应的平台,同时也 初始化了defaultCallAdapterFactory工厂

ServiceMethod

接口映射的网络请求对象,通过动态代理,将自定义接口的标注转换为该对象,将标注及参数生成 OkHttp所需的Request对象。Retrofit的create通过动态代理拦截,将每一个自定义接口转换成为一个 ServiceMethod对象,并通过通过serviceMethodCache进行缓存

Call

Retrofit定义的网络请求接口,包含execute、enqueue等方法

OkHttpCall

Ohttp的Call实现,通过createRawCall得到真正的 okhttp3.Call对象,用于进行实际的网络请求

CallAdapter.Factory

CallAdapter的静态工厂,包含get的抽象方法,用于生产CallAdapter对象

ExecutorCallAdapterFactory

Android平台默认的CallAdapter工厂,get方法使用匿名内部类实现CallAdapter,返回 ExecutorCallbackCall,实现了Call

ExecutorCallbackCall

采用静态代理设计,delegate实际为OkHttpCall,使用callbackExecutor实现回调在主线程中执行

RxJavaCallAdapterFactory

Rxjava平台的CallAdapter工厂,get方法返回RxJavaCallAdapter对象

RxJavaCallAdapter

Rxjava平台的适配器,返回observable对象

Converter.Factory

数据解析器工厂,用于生产Converter实例

GsonConverterFactory

数据解析工厂实例,返回了GsonResponseBodyConverter数据解析器

GsonResponseBodyConverter

Gson的数据解析器,将服务端返回的json对象转换成对应的java模型

Response

Retrofit网络请求响应的Response

关键的几个流程

  1. Retrofit 如何将定义的interface转换成网络请求?
    通过动态代理在ServiceMethod里面转换的

  2. Retrofit的Converter机制是如何实现?

  3. Retrofit的CallAdapter机制是如何实现?

通过debug单步调试我们能得出这个 流程图

Retrofit:Call
Response<T> execute() throws IOException;
void enqueue(Callback<T> callback);

创建retrofit对象的时候 创建了一个OkHttpClient 其实是OKHttp里面Call.Factory

OkHttp: Call 真正执行网络请求
这个Call对象 并不是创建Retrofit对象的时候创建

Converter种类

Retrofit支持多种数据解析方式,使用时需要在Gradle添加依赖。

数据解析器 Gradle依赖
Gson com.squareup.retrofit2:converter-gson:version
Jackson com.squareup.retrofit2:converter-jackson:version
Simple XML com.squareup.retrofit2:converter-simplexml:version
Protobuf com.squareup.retrofit2:converter-protobuf:version
Moshi com.squareup.retrofit2:converter-moshi:version
Wire com.squareup.retrofit2:converter-wire:version
Scalars com.squareup.retrofit2:converter-scalars:version

CallAdapter种类

网络请求适配器 Gradle依赖
guava com.squareup.retrofit2:adapter-guava:version
Java8 com.squareup.retrofit2:adapter-java8:version
rxjava com.squareup.retrofit2:adapter-rxjava:version

如何自定义一个Converter及CallAdapter?

CallAdapter

package top.zcwfeng.retrofitdemo.retrofit.calladapter

import androidx.lifecycle.LiveData
import retrofit2.*
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.concurrent.atomic.AtomicBoolean

class LiveDataCallAdapterFactory: CallAdapter.Factory(){

    companion object{
        @JvmStatic
        fun create() = LiveDataCallAdapterFactory()
    }

    override fun get(
        returnType: Type,
        annotations: Array<Annotation>,
        retrofit: Retrofit
    ): CallAdapter<*, *>? {
        val responseType: Type
        if(getRawType(returnType) != LiveData::class.java){
            throw IllegalStateException("return type must be parameterized")
        }
        val observableType = getParameterUpperBound(0,returnType as ParameterizedType)
        val rawObservableType = getRawType(observableType)
        responseType = if(rawObservableType == Response::class.java){
            if(observableType !is ParameterizedType){
                throw java.lang.IllegalStateException("Response must be parameterized")
            }
            getParameterUpperBound(0,observableType)
        }else{ observableType}
        return LiveDataCallAdapter<Any>(responseType)
    }

}

private class LiveDataCallAdapter<R>(private val responseType: Type): CallAdapter<R, LiveData<R>> {
    override fun adapt(call: Call<R>): LiveData<R> {
        return object : LiveData<R>(){
            private val startedFlag = AtomicBoolean(false)
            override fun onActive() {
                super.onActive()
                if(startedFlag.compareAndSet(false,true)){
                    call.enqueue(object: Callback<R> {
                        override fun onFailure(call: Call<R>, t: Throwable) {
                            postValue(null)
                        }

                        override fun onResponse(call: Call<R>, response: Response<R>) {
                            postValue(response.body())
                        }

                    })
                }
            }
        }
    }

    override fun responseType(): Type = responseType

}

Converter

package top.zcwfeng.retrofitdemo.retrofit.converter

import android.util.JsonToken
import com.google.gson.Gson
import com.google.gson.JsonIOException
import com.google.gson.TypeAdapter
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import okio.Buffer
import retrofit2.Converter
import retrofit2.Retrofit
import java.io.IOException
import java.io.OutputStreamWriter
import java.io.Writer
import java.lang.reflect.Type
import java.nio.charset.Charset

class MyGsonConvertFactory(private val gson:Gson): Converter.Factory() {

    companion object{
        fun create() = MyGsonConvertFactory(Gson())
        fun create(gson:Gson?):MyGsonConvertFactory{
            if(gson == null){
                throw NullPointerException("gson == null")
            }
            return MyGsonConvertFactory(gson)
        }
    }

    override fun requestBodyConverter(
        type: Type,
        parameterAnnotations: Array<Annotation>,
        methodAnnotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<*, RequestBody>? {
       val adapter = gson.getAdapter(TypeToken.get(type))
       return null
    }

    override fun responseBodyConverter(
        type: Type,
        annotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<ResponseBody, *>? {
        val adaptation = gson.getAdapter(TypeToken.get(type))
        return null
    }

    private class MyGsonResponsesBodyConvert<T>(

        private val gson:Gson,
        private val  adapter:TypeAdapter<T>
    ):Converter<ResponseBody,T>{
        override fun convert(value: ResponseBody): T? {
           val jsonReader:JsonReader = gson.newJsonReader(value.charStream())

            return try {
                val result = adapter.read(jsonReader)
                if(jsonReader.peek() != JsonToken.END_DOCUMENT){
                    throw JsonIOException("JSON document was not fully consumed.")
                }
                result
            }finally {
                value.close()
            }
        }


    }


    private class MyGsonRequestBodyConverter<T>(
        private val gson: Gson,
        private val adapter: TypeAdapter<T>
    ) :
        Converter<T, RequestBody> {
        @Throws(IOException::class)
        override fun convert(value: T): RequestBody {
            val buffer = Buffer()
            val writer: Writer =
                OutputStreamWriter(buffer.outputStream(), UTF_8)
            val jsonWriter: JsonWriter = gson.newJsonWriter(writer)
            adapter.write(jsonWriter, value)
            jsonWriter.close()
            return RequestBody.create(
                MEDIA_TYPE,
                buffer.readByteString()
            )
        }

        companion object {
            private val MEDIA_TYPE: MediaType = MediaType.get("application/json; charset=UTF-8")
            private val UTF_8: Charset = Charset.forName("UTF-8")
        }

    }


}

Java 版本的String Convert

static class ToStringConverterFactory extends Converter.Factory {
        private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");

        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            if (String.class.equals(type)) {
                return new Converter<ResponseBody, String>() {
                    @Override
                    public String convert(ResponseBody value) throws IOException {
                        return value.string();
                    }
                };
            }
            return null;
        }

        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

            if (String.class.equals(type)) {
                return new Converter<String, RequestBody>() {
                    @Override
                    public RequestBody convert(String value) throws IOException {
                        return RequestBody.create(MEDIA_TYPE, value);
                    }
                };
            }
            return null;
        }
    }

Retrofit中的设计模式

  1. 建造者模式
    Retrofit对象的创建、ServiceMethod对象创建都使用Build模式,将复杂对象的创建和表示分离,调用 者不需要知道复杂的创建过程,使用Build的相关方法进行配置创建对象。

  2. 外观模式
    Retrofit对外提供了统一的调度,屏蔽了内部的实现,使得使用该网络库简单便捷。
    门面模式: 提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一 个统一的高层接口。使用子系统更容易使用

  1. 动态代理模式 通过动态代理的方式,当调用Retrofit的create()方法时,会进行动态代理监听。当执行具体的接口方法
    时,会回调InvocationHandler。通过反射解析method的标注及参数,生成ServiceMethod对象。

  2. 静态代理模式 Android平台默认的适配器ExecutorCallbackCall,采用静态代理的模式。具体的实现delegate为 OkHttpCall。

  3. 工厂模式 Converter及CallAdapter的创建都采用了工厂模式进行创建。

  4. 适配器模式 CallAdapter的adapt采用了适配器模式,使得interface的返回对象可以动态扩展,增强了灵活性

题外话

所谓:OkHttp 请求速度快 针对连接池进行了复用,用 Okio 优化 socket链接

是对和HttpConnection HttpClient socket链接 角度进行的描述

Volley 和Retrofit是对 网络请求的封装解耦

举报

相关推荐

0 条评论