Retrofit原理分析

一、Retrofit简介

Retrofit是现下Android端开发非常流行的一款网络请求框架,它通过动态代理的方式将Java接口翻译成网络请求,通过OkHttp发送请求,并且其具备强大的可扩展性,支持各种数据格式的转换以及RxJava。说到这里,我们来分析一下网络请求框架的本质,网络请求框架是一套提供给开发者使用的用于网络请求的API接口,我们知道,Android网络请求一般是基于Http协议的,而Http协议属于应用层的协议,具体的数据传输需要依赖传输层的TCP协议,Android系统提供了Socket编程接口给开发者建立TCP请求,所以具体数据的发送需要依赖Socket;Http协议属于应用层的协议,它是用来规定数据的传输格式的,用于传输双方都能按照固定的格式解读数据;所以,一个网络请求框架至少要包含以下几个功能:

1、提供接口给开发者传入请求参数;

2、编写Socket代码,建立TCP;

3、通过TCP连接,严格按照Http协议的格式将请求参数发送给服务端;

4、严格按照Http协议的格式解读服务端返回的数据;

5、提供相应的接口给开发者获得返回数据(一般是通过回调处理的)。

上面五点是一个网络请求框架必须具备的功能,当然,一个好的网络请求框架还应该具备如下特点:

1、提供给开发者使用的API尽可能简单;

2、添加了对网络缓存的处理,避免不必要的请求;

3、具有较高的性能;

4、具有较高的可扩展性。

我们常用的OkHttp、HttpURLConnection等网络请求框架,其内部就会将开发者传入的请求参数按照Http协议的格式组织好,并通过TCP连接发送给服务端,在收到服务端返回数据后,又会按照Http协议去解读数据,并提供相应的API(一般是回调)给开发者获得数据。由于OkHttp属于比较底层的网络请求框架,开发者在使用时还是会比较复杂,于是Retrofit对OkHttp进行了再度的封装,使得开发者在使用时更加的方便。

二、使用Retrofit请求网络数据的基本流程

1、在build中添加依赖

compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

2、定义请求接口类


import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
 
/**
 * Created by dell on 2018/9/6.
 */
 
public interface TranslateApi {
    @POST("ajax.php?a=fy&f=auto&t=auto")
    @FormUrlEncoded
    Call<TranslateBean> translateRequest(@Field("w") String input);
}

3、创建Retrofit实例

 Retrofit retrofit = new Retrofit.Builder() // 通过Builder模式构造一个Retrofit对象
                .baseUrl("http://fy.iciba.com/") // 配置HOST
                .addConverterFactory(GsonConverterFactory.create()) // 添加解读返回数据的对象,因为返回数据是Json格式的,所以这里采用GsonConverterFactory来解读
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加适配OkHttpCall对象的CallAdapterFactory
                .build();

4、根据请求接口生成具体的请求实体对象

TranslateApi translateApi = retrofit.create(TranslateApi.class); // 传入定义的接口,获得一个实现了TranslateApi接口的实体对象

5、调用请求对象的请求方法生成能够发起网络请求的Call对象

Call<TranslateBean> call = translateApi.translateRequest(mInputEditText.getText().toString()); // 调用请求方法,返回一个Call对象

6、调用Call对象的enqueue方法发起异步网络请求


        call.enqueue(new Callback<TranslateBean>() { // 调用Call对象的enqueue方法发起异步网络请求,enqueue方法需要传入一个Callback对象,用来处理网络请求的回调
            @Override
            public void onResponse(Call<TranslateBean> call, Response<TranslateBean> response) { // 网络请求正确的回调
                TranslateBean translateBean = response.body(); // 处理返回结果
                if (translateBean.getContent().getOut() != null) {
                    mOutputText.setText(translateBean.getContent().getOut());
                } else {
                    mOutputText.setText(translateBean.getContent().getWordMeanString());
                }
            }
 
            @Override
            public void onFailure(Call<TranslateBean> call, Throwable t) { // 网络请求错误的回调
                mOutputText.setText("翻译出错了!");
            }

总结一下,首先我们定义了网络请求的接口,接口中配置了请求的基本信息,包括请求方法、请求参数等;接着我们生成了一个Retrofit对象,在这里可以配置请求的默认Host信息、添加解析返回数据格式的Factory、添加适配OkHttpCall的Factory等功能;然后调用retrofit对象的create方法,传入网络请求接口类,生成一个具体的网络请求实体对象;接下来我们调用了请求方法生成一个能够发起网络请求的Call对象,最后调用Call对象的enquene方法将发起异步的网络请求,并且在传入的Callback中处理网络请求的回调。

三、Retrofit原理分析

从上面的使用方法可以看出,Retrofit的核心是根据接口生成一个能够发起网络请求的对象,然后根据这个对象再发起网络请求

1、生成Retrofit对象

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient(); // 如果没有设置网络请求框架,模式使用OkHttp处理网络请求
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor(); // 默认使用platform.defaultCallbackExecutor()处理返回结果
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly); // 根据配置信息生成一个Retrofit对象
    }
  }

Retrofit通过build模式来生成一个Retrofit对象,通过代码我们知道,Retrofit默认会使用OkHttp来发送网络请求,当然,我们也可以自己定制。

2、create方法根据接口生成具体的网络请求实体类

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, // 通过动态代理的方式生成具体的网络请求实体对象
        new InvocationHandler() { // 统一处理所有的请求方法
          private final Platform platform = Platform.get();

          @Override public 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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);  // 根据方法生成一个ServiceMethod对象(内部会将生成的ServiceMethod放入在缓存中,如果已经生成过则直接从缓存中获取)
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); // 根据ServiceMethod对象和请求参数生成一个OkHttpCall对象,这个OkHttpCall能够调用OkHttp的接口发起网络请求
            return serviceMethod.callAdapter.adapt(okHttpCall); // 调用serviceMethod的callAdapter的adapt方法,并传入okHttpCall,返回一个对象,这个的目的主要是为了适配返回类型,其内部会对OkhttpCall对象进行包装
          }
        });
  }

Retrofit的create方法通过动态代理的模式,生成了实现了具体的网络请求接口的对象,并在InvocationHandler的invoke方法中统一处理网络请求接口实体对象的方法,invoke方法会通过方法构造一个ServiceMethod对象,并将其放入缓存中,然后根据ServiceMethod对象和网络请求的参数args去构造一个OkHttpCall对象,最后调用serviceMethod的callAdapter的adapt方法,传入将OkHttpCall对象,callAdapter的目的主要是为了适配OkHttpCall对象,其内部会对OkHttpCall对象进行包装,生成对应返回类型的对象。

动态代理的原理主要是在运行时动态生成代理类,然后根据代理类生成一个代理对象,在这个代理对象的方法中中又会调用InvocationHandler的invoke来转发对方法的处理,比如,TranslateApi生成的代码类代码大致应该如下:

public Class Translate implement Translate {
	InvokeHandler mInvokeHandler;

	Call<TranslateBean> translateRequest(String input) {
		Method translateRequestMethod = Class.forName("packagename.TranslateApi").getMethod("translateRequest", String.class); // 通过反射获得TranslateApi的translateRequest方法
		mInvokeHandler.invoke(this, translateRequestMethod, new Object[] {input}); // 调用InvokeHandler的invoke方法,并传入当前对象,方法,方法传入参数
	}
}

代理类的代码是动态生成的,生成代码后我们就可以用ClassLoader将其加载到内存中,并通过反射生成代理对象,代理类会将方法的处理转发给InvokeHandler,所以所有对代理对象方法的调用都会由InvocationHandler的invoke方法处理。

3、loadServiceMethod方法

  ServiceMethod<?, ?> loadServiceMethod(Method method) { // 根据方法返回一个对应的ServiceMethod对象
    ServiceMethod<?, ?> result = serviceMethodCache.get(method); // 首先从缓存中获取
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) { // 如果缓存中没有则构造一个ServiceMethod对象并将其放入缓存中
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

loadServiceMethod首先会从缓存中获取ServiceMethod对象,如果没有,则通过Method和Retrofit对象构造一个ServiceMethod对象,并将其放入缓存中。

4、ServiceMethod的构造

ServiceMethod其实是用来存储一次网络请求的基本信息的,比如Host、URL、请求方法等,同时ServiceMethod还会存储用来适配OkHttpCall对象的CallAdpater。ServiceMethod的build方法会解读传入的Method,首先ServiceMethod会在CallAdpaterFactory列表中寻找合适的CallAdapter来包装OkHttpCall对象,这一步主要是根据Method的返回参数来匹配的,比如如果方法的返回参数是Call对象,那么ServiceMethod就会使用默认的CallAdpaterFactory来生成CallAdpater,而如果返回对象是RxJava的Obserable对象,则会使用RxJavaCallAdapterFactory提供的CallAdpater。然后build方法会解读Method的注解,来获得注解上配置的网络请求信息,比如请求方法、URL、Header等。

    public ServiceMethod build() {
      callAdapter = createCallAdapter(); // 查找能够适配返回类型的CallAdpater
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      // 解读方法的注解
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

我们来看一下查找CallAdpater的代码:

    private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType(); // 获得方法的返回类型
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); // 调用retrofit的callAdpater方法查找合适的CallAdpater
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

可以看到,会调用retrofit的callAdapter去查找合适的CallAdapter,传入的参数为方法的返回类型和注解

Retrofit的callAdapter方法:

  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) { // 遍历所有的CallAdpaterFactory,找到能够适配的CallAdpater
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    ...
  }

Retrofit的CallAdpater方法会遍历所有的CallAdpaterFactory,找到能够适配的CallAdpater,我们首先来看一下默认的CallAdpaterFactory是如何生成CallAdapter的:

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) { // 首先判断方法的返回类型是不是Call类型,如果不是则说明这个CallAdpaterFactory适配不了
      return null;
    }

    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() { // 返回CallAdpater
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return call; // 直接将call返回
      }
    };
  }
}

DefaultCallAdapterFactory是默认的CallAdpaterFactory,它在Retrofit构造时会加入到CallAdapterFactory列表中,可以看到,它只会去适配返回类型为Call的方法。

我们再来看一下返回类型为Observable是如何适配的:

首先,我们在构造Retrofit对象时需要加入适配RxJava返回对象的

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

我们来看一下RxJava2CallAdpaterFactory的get方法:

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType); // 获得返回类型

    if (rawType == Completable.class) { // 如果返回类型为RxJava的Completable类型,则可以适配
      // Completable is not parameterized (which is what the rest of this method deals with) so it
      // can only be created with a single configuration.
      return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
          false, true);
    }

    boolean isFlowable = rawType == Flowable.class;
    boolean isSingle = rawType == Single.class;
    boolean isMaybe = rawType == Maybe.class;
    // 如果返回类型为RxJava的Flowable、Single、Maybe、Observable类型,则可以适配
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null;
    }

    boolean isResult = false;
    boolean isBody = false;
    Type responseType;
    if (!(returnType instanceof ParameterizedType)) {
      String name = isFlowable ? "Flowable"
          : isSingle ? "Single"
          : isMaybe ? "Maybe" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + "<Foo> or " + name + "<? extends Foo>");
    }

    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    Class<?> rawObservableType = getRawType(observableType);
    if (rawObservableType == Response.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Response must be parameterized"
            + " as Response<Foo> or Response<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
    } else if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"
            + " as Result<Foo> or Result<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      isResult = true;
    } else {
      responseType = observableType;
      isBody = true;
    }

    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }

可以看到,RxJava2CallAdpaterFactory能够处理返回类型为RxJava的Completable、Flowable、Single、Maybe、Observable类型,并提供一个RxJava2CallAdpater适配器。

5、根据ServiceMethod和args生成OkHttpCall对象

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

我们知道,ServiceMethod封装了网络请求的基本信息,比如Host、URL等,我们根据ServiceMethod和请求参数args就可以确定本次网络请求的所有信息了,OkHttpCall主要是将这些信息封装起来,并调用OkHttp的接口去发送网络请求,这里,我们就将OkHttpCall看成是一个处理网络请求的类即可。

6、serviceMethod.callAdpater.adpat(okHttpCall)

这一步主要是将能够处理网络请求的OkHttpCall对象通过适配器适配成方法返回类型的对象,以Observable为例,我们知道RxJava和Retrofit结合使用的代码大致如下:

Observable<DataBean> observable = requestApi.request("xiaoming");
observable.subscribleOn(Sechedulers.io())
         .observerOn(AndroidSecheduler.mainThread())
         .subscrible(new Observer() {
         	public void onNext(DataBean dataBean) {

         	}
         	public void onError(Error e) {

         	}
         	...
         })

也就是说我们通过调用接口返回了一个observable(被观察者)对象,然后给obserable绑定了一个Observer(观察者)对象,并且指定了处理的subscrible线程为子线程,处理observer回调的线程为主线程。

那么RxJava2CallAdapter的adapt方法是如何将一个Call对象适配成Observable对象的呢?

final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {

  @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call); // 生成自定义的Observable对象,并且其中封装了进行网络请求的Call对象

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

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }
}

主要看第一行代码:

Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call); // 生成自定义的Observable对象,并且其中封装了进行网络请求的Call对象

这句代码会将能够进行网络请求的Call对象封装成一个自定义的Observable对象并返回,以CallExecuteObservable为例:

final class CallExecuteObservable<T> extends Observable<Response<T>> {
  private final Call<T> originalCall; // 能够进行网络请求的Call对象,也就是我们前面说的OkHttpCall对象

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

  @Override protected void subscribeActual(Observer<? super Response<T>> observer) { // 这个方法会在Observable调用subscribe方法订阅观察者时调用
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    observer.onSubscribe(new CallDisposable(call));

    boolean terminated = false;
    try {
      Response<T> response = call.execute(); // 调用OkHttpCall对象,执行网络请求并获得响应结果
      if (!call.isCanceled()) {
        observer.onNext(response); // 调用Obserber的onNext方法,发送返回接口
      }
      if (!call.isCanceled()) {
        terminated = true;
        observer.onComplete();
      }
    } catch (Throwable t) {
      Exceptions.throwIfFatal(t);
      if (terminated) {
        RxJavaPlugins.onError(t);
      } else if (!call.isCanceled()) {
        try {
          observer.onError(t); // 请求出错则调用Observer的onError方法
        } catch (Throwable inner) {
          Exceptions.throwIfFatal(inner);
          RxJavaPlugins.onError(new CompositeException(t, inner));
        }
      }
    }
  }

  ...
}

可以看到CallExecuteObserable继承了Obserable,并重写了其subscribeActual方法,subscribeActual会在Obserable对象调用subcrible方法时调用,在subscribeActual方法中,首先是调用了OkHttpCall的execute()方法发起网络请求,并获得网络请求结果,如果请求成功,会调用Observer的onNext方法,并将请求结果传递给onNext方法,所以我们可以在Observer的onNext方法种处理网络请求成功的情况,而如果网络请求失败,则会调用Observer的onError方法。由上,我们知道,CallAdapter的作用是将OkHttpCall对象适配成方法的返回类型的对象。

至此,我们知道了Retrofit的原理,它内部通过动态代理生成接口的实体对象,然后通过解读注解来获得接口中定义的请求信息,通过CallAdapterFactory将OkHttpCall对象适配成接口中定义的返回类型,通过ConverFactory来解读数据,其底层真正处理网络请求的还是OkHttp框架(OkHttpCall通过调用OkHttp框架提供的Api处理网络请求)。

四、总结

Retrofit是一款能够将Java接口转换成一个能够进行网络请求对象的框架,具有使用简单,可扩展性强等优点,其内部通过动态代理模式生成接口的实体对象,并且在InvocationHandler中统一处理请求方法,通过解读方法的注解来获得接口中配置的网络请求信息,并将网络请求信息和请求参数一起封装成一个OkHttpCall对象,这个OkHttpCall对象内部通过OkHttp提供的Api来处理网络请求,为了将OkHttpCall对象适配成方法的返回类型,Retrofit提供了配置CallAdpaterFactory的Api,比如RxJava2CallAdapterFactory就会将OkHttpCall对象适配成一个Observable对象,并在Obserable的subscribleActual方法中调用OkHttpCall对象发起网络请求并回调Observser的onNext方法来处理网络请求返回的数据。Retrofit还提供了配置数据格式转换的API,可以针对不同的数据类型进行处理。

反观一下Retrofit,其内部的设计结构非常清晰,通过动态代理来处理接口,通过OkHttp来处理网络请求,通过CallAdapterFactory来适配OkHttpCall,通过ConverterFactory来处理数据格式的转换,这符合面对对象设计思想的单一职责原则,同时,Retrofit对CallAdpaterFactory和ConverterFactory的依赖都是依赖其接口的,这就让我们可以非常方便的扩展自己的CallAdpaterFactory和ConverterFactory,这符合依赖倒置原则;不管Retrofit内部的实现如何复杂,比如动态代理的实现、针对注解的处理以及寻找合适的适配器等,Retrofit对开发者隐藏了这些实现细节,只提供了简单的Api给开发者调用,开发者只需要关注通过的Api即可实现网络请求,这种对外隐藏具体的实现细节的思想符合迪米特原则。另外,Retrofit内部大量使用了设计模式,比如构造Retrofit对象时使用了Builder模式,处理接口时是用来动态代理模式,适配OkHttpCall时使用了Adapter模式,生成CallAdpater和Converter时使用了工厂模式。Retrofit的设计正是因为遵循了面向对象的思想,以及对设计模式的正确应用,才使得其具备结构清晰、易于扩展的特点。

  • 10
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值