Retrofit设计模式

2024-01-09  本文已影响0人  freelifes

本文主要介绍Retrofit用到的设计模式,包括代理模式,工厂方法模式,抽象工厂模式,适配器模式,建造者模式,策略模式。

1、Retrofit基本使用

1.1、定义Service

interface Service {
     @Headers(
        "Cache-Control: max-age=640000, max-stale=864000",
        "Authorization: APPCODE " + APP_CODE,
    )
    @GET("/{path}")
    fun getDate(
        @Path("path") path: String,
        @QueryMap() map: MutableMap<String, String>
    ): Observable<Any>
}

1.2、创建代理对象,执行请求

        val executorService = Executors.newCachedThreadPool();
        var okHttpClient = OkHttpClient.Builder().dispatcher(Dispatcher(executorService))
            .addInterceptor label@{
                Log.d(TAG, "getNetWork1:  数据请求发起线程  " + Thread.currentThread().name)
                return@label it.proceed(it.request())
            }
            .addNetworkInterceptor(object : Interceptor {
                override fun intercept(chain: Interceptor.Chain): Response {
                    Log.d(TAG, "intercept: ------进行了网络请求" + Thread.currentThread().name)
                    var request = chain.request()
                    Log.d(TAG, "intercept: " + request.toString())
                    return chain.proceed(request)
                }
            }).cache(Cache(file, 10 * 1024 * 1024))
            .build()
        var retrofit = Retrofit.Builder().baseUrl(RetrofitActivity.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClient)
            //异步结果返回的线程。就是enqueue的caback所在线程,默认主线程。
            .callbackExecutor(Executors.newCachedThreadPool())
            .build()
        // retrofit.callFactory().newCall()
        var service = retrofit.create(Service::class.java)
        service.getDate4(
            path = "area-to-weather-date",
            map = mutableMapOf<String, String>(
                "area" to "丽江",
                "areaCode" to "530700",
                "date" to "20200319",
                "need3HourForcast" to "1"
            )
        ).observeOn(Schedulers.newThread()).subscribe {
            Log.d(TAG, "onResponse: exec数据返回线程 " + Thread.currentThread().name + " ")
            tvContent?.setText("" + it.toString())
        }

2、Retrofit调用流程

调用流程

  创建Service代理对象,调用Service中的方法,解析注解,构建RequestFactroy,这个用于创建request,解析注解包括解析方法注解,解析使用的请求方式,GET、POST请求,解析参数注解,传参如FieldMap注解,通过传入的CalladapterFactroy拿到CallAdapter,通过传入的ConvertFactroy拿到Convert,返回HttpServiceMethod的子类CallAdapted<>。
  invoke创建OKhttpCall,执行同步和异步请求,使用上面解析完成的RequestFactroy创建Request,创建okhttp的call,执行请求,返回ResponseBody,body再通过转化为Response<JavaBean>,再通过callBack回调给RxJavaCalladapter处理成Observable对象,最终用Object接收,返回给动态代理中作为方法的返回值。
2.1、创建代理对象,解析注解。

//  Retrofit
 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 {
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

2.2、创建OkhttpCall

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

2.3、以RxJava2CallAdapter为例,执行请求

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

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

        @Override public Object adapt(Call<R> call) {
            Observable<Response<R>> responseObservable = isAsync
                    ? new CallEnqueueObservable<>(call)
                    : new CallExecuteObservable<>(call);
            return observable;
        }
}

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) {
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    call.enqueue(callback);
  }
}

这里的Call是OKHttpCall,调用enqueue,执行真正的call请求,返回结果给CallEnqueueObservable 的callback,调用 observer.onNext(response)向下传递,包装成了Observable对象。

2.4、执行真正的请求

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

        synchronized (this) {
            try {
                call = rawCall = createRawCall();
            }
        }

        call.enqueue(
                new okhttp3.Callback() {
                    @Override
                    public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                        Response<T> response;
                        try {
                            response = parseResponse(rawResponse);
                        }

                        try {
                            callback.onResponse(OkHttpCall.this, response);
                        }
                    }
                });
    }

 private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    return call;
  }

requestFactory.create(args)构建request,将方法参数解析的结果添加到request里面。

2.5、返回ResponseBody转化成Response<DataBean>

// OkHttpCall
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
        rawResponse =
                rawResponse
                        .newBuilder()
                        .body(new OkHttpCall.NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
                        .build();

        int code = rawResponse.code();
        ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
        try {
            T body = responseConverter.convert(catchingBody);
            return Response.success(body, rawResponse);
        } 
    }

3、动态代理模式

  执行Service方法使用了代理模式。
  好处1、 比如使用某个网络框架请求数据,后来换成其他网络请求框架,如果不使用代理模式,需要将使用的地方删除,可能很多。使用代理,只会改掉代理里面的就可以了。
  好处2、如果被代理者3个方法,被代理者只授权使用2个,那么就可以使用代理模式了,避免客户直接访问被代理者的受限方法。


代理模式.png
public static Object newProxyInstance(ClassLoader loader,
                                        Class<?>[] interfaces,
                                        InvocationHandler h)

4、建造者模式

  创建Retrofit、RequestFactroy使用了建造者模式。
  好处: 将对象的实现细节,封装在内部,高内聚。相同的构建过程,可以创建不同的产品。


建造者.png
 // RequestFactory
 RequestFactory(Builder builder) {
    method = builder.method;
    baseUrl = builder.retrofit.baseUrl;
    httpMethod = builder.httpMethod;
    relativeUrl = builder.relativeUrl;
    headers = builder.headers;
    contentType = builder.contentType;
    hasBody = builder.hasBody;
    parameterHandlers = builder.parameterHandlers;
  }
  
   //Builder
    RequestFactory build() {
        for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
        }
        int parameterCount = parameterAnnotationsArray.length;
        parameterHandlers = new ParameterHandler<?>[parameterCount];
        for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
            parameterHandlers[p] =
                    parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
        }
        return new RequestFactory(this);
    }

5、工厂模式

1.1、创建CallAdapter使用了工厂方法模式
   相比较简单工厂,简单工厂再创建adapter,需要修改factroy类,所以一般框架都是使用工厂方法和抽象工厂,避免修改,对修改关闭,对扩展开放。


工厂方法模式
abstract class Factory {

    public abstract @Nullable CallAdapter<?, ?> get(
        Type returnType, Annotation[] annotations, Retrofit retrofit);

}

public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
  
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {

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

}

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

     @Override public Object adapt(Call<R> call) {
 
    }
}

  每一个CallAdapter的子类型Adapter对应一个Factroy的子类型工厂。 CallAdapter主要负责在adapt方法中请求数据,配置Retrofit时,传递的不同Factroy,决定了不同的Adpter。

1.2、创建Converter对象使用了抽象工厂模式
   Factory创建同一类的多个相类似的产品,也避免了在Factory中修改。


抽象工厂模式

    public final class GsonConverterFactory extends Converter.Factory {

        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(
                Type type, Annotation[] annotations, Retrofit retrofit) {
            TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
            return new GsonResponseBodyConverter<>(gson, adapter);
        }

        @Override
        public Converter<?, RequestBody> requestBodyConverter(
                Type type) {
            TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
            return new GsonRequestBodyConverter<>(gson, adapter);
        }
    }

    final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
        
        private final TypeAdapter<T> adapter;

        @Override
        public T convert(ResponseBody value) throws IOException {
            JsonReader jsonReader = gson.newJsonReader(value.charStream());
            try {
                T result = adapter.read(jsonReader);
                return result;
            }
        }
    }

  可以看到每个工厂可以创建2个Converter,以GsonConverterFactory为例,一个工厂创建了GsonRequestBodyConverter和GsonResponseBodyConverter对象。GsonRequestBodyConverter负责将ResponseBody通过Gson转化成ResponType类型。GsonRequestBodyConverter将传入的java对象写入到RequestBody中。

6、适配器模式

  将某个类的接口转化为客户端期望的另一个接口表示,主要的目的是兼容性,让原本不匹配不能一起工作的两个类可以协同工作。


适配器模式
// 创建
new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

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

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


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

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

        @Override public Object adapt(Call<R> call) {
            Observable<Response<R>> responseObservable = isAsync
                    ? new CallEnqueueObservable<>(call)
                    : new CallExecuteObservable<>(call);
            return observable;
        }
    }

    final class CallEnqueueObservable<T> extends Observable<Response<T>> {
        private final Call<T> originalCall;

        @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
            Call<T> call = originalCall.clone();
            CallCallback<T> callback = new CallCallback<>(call, observer);
            observer.onSubscribe(callback);
            call.enqueue(callback);
        }

        private static final class CallCallback<T> implements Disposable, Callback<T> {

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

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

                try {
                    observer.onNext(response);
                }
            }
        }
    }

  HttpServiceMethod类通过CallFactroy、responseConverter、callAdapter创建OkhttpCall对象,并且抽象了adapt方法,这个方法负责请求数据。
   子类CallAdapted 实现adapt方法,执行Call请求,但是该方法的具体实现在CallAdapter中的adapt中实现的。
   比如上述的CallAdapter为RxJava2CallAdapter时,执行Call请求在RxJava2CallAdapter的adapt方法中,执行adapt方法返回了Observable<Response<R>>类型。


适配器模式
    final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {

        private final TypeAdapter<T> adapter;

        @Override
        public T convert(ResponseBody value) throws IOException {
            JsonReader jsonReader = gson.newJsonReader(value.charStream());
            try {
                T result = adapter.read(jsonReader);
                return result;
            }
        }
    }

  基类中Convert中将ResponseBody转化成泛型T,子类GsonResponseConverter实现了Convert方法,该类持有TypeAdapter对象,真正转化是在ObjectTypeAdapter中实现的。

   // OkHttpCall 
    Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
        rawResponse =
                rawResponse
                        .newBuilder()
                        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
                        .build();
        int code = rawResponse.code();
        ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
        try {
            T body = responseConverter.convert(catchingBody);
            return Response.success(body, rawResponse);
        } 
    }

   Adapter将stream转化成需要的对象,比如DateBean,包转成Response<DateBean>返回。

7、策略模式

策略模式

3.1、解析注解,生成ParameterHandler

private ParameterHandler<?> parseParameterAnnotation(
            int p, Type type, Annotation[] annotations, Annotation annotation) {
        if (annotation instanceof FieldMap) {
            validateResolvableType(p, type);
            Class<?> rawParameterType = Utils.getRawType(type);
            Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
            ParameterizedType parameterizedType = (ParameterizedType) mapType;
            Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
            Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
            Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);
            gotField = true;
            return new ParameterHandler.FieldMap<>(
                    method, p, valueConverter, ((FieldMap) annotation).encoded());
        } else if (annotation instanceof Body) {
            validateResolvableType(p, type);
            Converter<?, RequestBody> converter;
            try {
                converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
            }
            gotBody = true;
            return new ParameterHandler.Body<>(method, p, converter);
        }
    }

3.2、实现ParameterHandler接口,重写apply()方法

 static final class FieldMap<T> extends ParameterHandler<Map<String, T>> {
    
        private final Converter<T, String> valueConverter;
        private final boolean encoded;
        

        @Override
        void apply(RequestBuilder builder, @Nullable Map<String, T> value) throws IOException {
       
            for (Map.Entry<String, T> entry : value.entrySet()) {
                String entryKey = entry.getKey();
                T entryValue = entry.getValue();
                
                String fieldEntry = valueConverter.convert(entryValue);
                builder.addFormField(entryKey, fieldEntry, encoded);
            }
        }
    }

3.3、使用ParameterHandler对象。

//  OkHttpCall
private okhttp3.Call createRawCall() throws IOException {
        okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
        return call;
    }

// RequestFactory
 okhttp3.Request create(Object[] args) throws IOException {

        ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
        int argumentCount = args.length;

        RequestBuilder requestBuilder =
                new RequestBuilder(
                        httpMethod,
                        baseUrl,
                        relativeUrl,
                        headers,
                        contentType,
                        hasBody,
                        isFormEncoded,
                        isMultipart);

        List<Object> argumentList = new ArrayList<>(argumentCount);
        for (int p = 0; p < argumentCount; p++) {
            argumentList.add(args[p]);
            handlers[p].apply(requestBuilder, args[p]);
        }
        return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
    }

okhttp执行同步或者异步请求时,调用createRawCall方法,接着调用create方法,调用handlers[p].apply,将参数设置给requestBuilder,返回request。

总结

   Retrofit使用到了很多模式,除了上述,还使用了比如常见模板设计模式,装饰设计模式,原型模式、门面模式、观察者模式等。

上一篇下一篇

猜你喜欢

热点阅读