美文网首页
Retrofit设计模式

Retrofit设计模式

作者: freelifes | 来源:发表于2024-01-09 14:12 被阅读0次

    本文主要介绍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使用到了很多模式,除了上述,还使用了比如常见模板设计模式,装饰设计模式,原型模式、门面模式、观察者模式等。

    相关文章

      网友评论

          本文标题:Retrofit设计模式

          本文链接:https://www.haomeiwen.com/subject/hvkundtx.html