Retrofit設(shè)計(jì)模式

本文主要介紹Retrofit用到的設(shè)計(jì)模式,包括代理模式,工廠方法模式,抽象工廠模式,適配器模式,建造者模式,策略模式。

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、創(chuàng)建代理對(duì)象,執(zhí)行請(qǐng)求

        val executorService = Executors.newCachedThreadPool();
        var okHttpClient = OkHttpClient.Builder().dispatcher(Dispatcher(executorService))
            .addInterceptor label@{
                Log.d(TAG, "getNetWork1:  數(shù)據(jù)請(qǐng)求發(fā)起線程  " + Thread.currentThread().name)
                return@label it.proceed(it.request())
            }
            .addNetworkInterceptor(object : Interceptor {
                override fun intercept(chain: Interceptor.Chain): Response {
                    Log.d(TAG, "intercept: ------進(jìn)行了網(wǎng)絡(luò)請(qǐng)求" + 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)
            //異步結(jié)果返回的線程。就是enqueue的caback所在線程,默認(rèn)主線程。
            .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數(shù)據(jù)返回線程 " + Thread.currentThread().name + " ")
            tvContent?.setText("" + it.toString())
        }

2、Retrofit調(diào)用流程

調(diào)用流程

??創(chuàng)建Service代理對(duì)象,調(diào)用Service中的方法,解析注解,構(gòu)建RequestFactroy,這個(gè)用于創(chuàng)建request,解析注解包括解析方法注解,解析使用的請(qǐng)求方式,GET、POST請(qǐng)求,解析參數(shù)注解,傳參如FieldMap注解,通過傳入的CalladapterFactroy拿到CallAdapter,通過傳入的ConvertFactroy拿到Convert,返回HttpServiceMethod的子類CallAdapted<>。
??invoke創(chuàng)建OKhttpCall,執(zhí)行同步和異步請(qǐng)求,使用上面解析完成的RequestFactroy創(chuàng)建Request,創(chuàng)建okhttp的call,執(zhí)行請(qǐng)求,返回ResponseBody,body再通過轉(zhuǎn)化為Response<JavaBean>,再通過callBack回調(diào)給RxJavaCalladapter處理成Observable對(duì)象,最終用Object接收,返回給動(dòng)態(tài)代理中作為方法的返回值。
2.1、創(chuàng)建代理對(duì)象,解析注解。

//  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、創(chuàng)建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為例,執(zhí)行請(qǐng)求

 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,調(diào)用enqueue,執(zhí)行真正的call請(qǐng)求,返回結(jié)果給CallEnqueueObservable 的callback,調(diào)用 observer.onNext(response)向下傳遞,包裝成了Observable對(duì)象。

2.4、執(zhí)行真正的請(qǐng)求

//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)構(gòu)建request,將方法參數(shù)解析的結(jié)果添加到request里面。

2.5、返回ResponseBody轉(zhuǎn)化成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、動(dòng)態(tài)代理模式

??執(zhí)行Service方法使用了代理模式。
??好處1、 比如使用某個(gè)網(wǎng)絡(luò)框架請(qǐng)求數(shù)據(jù),后來換成其他網(wǎng)絡(luò)請(qǐng)求框架,如果不使用代理模式,需要將使用的地方刪除,可能很多。使用代理,只會(huì)改掉代理里面的就可以了。
??好處2、如果被代理者3個(gè)方法,被代理者只授權(quán)使用2個(gè),那么就可以使用代理模式了,避免客戶直接訪問被代理者的受限方法。


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

4、建造者模式

??創(chuàng)建Retrofit、RequestFactroy使用了建造者模式。
??好處: 將對(duì)象的實(shí)現(xiàn)細(xì)節(jié),封裝在內(nèi)部,高內(nèi)聚。相同的構(gòu)建過程,可以創(chuàng)建不同的產(chǎn)品。


建造者.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、創(chuàng)建CallAdapter使用了工廠方法模式
?? 相比較簡單工廠,簡單工廠再創(chuàng)建adapter,需要修改factroy類,所以一般框架都是使用工廠方法和抽象工廠,避免修改,對(duì)修改關(guān)閉,對(duì)擴(kuò)展開放。


工廠方法模式
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) {
 
    }
}

??每一個(gè)CallAdapter的子類型Adapter對(duì)應(yīng)一個(gè)Factroy的子類型工廠。 CallAdapter主要負(fù)責(zé)在adapt方法中請(qǐng)求數(shù)據(jù),配置Retrofit時(shí),傳遞的不同F(xiàn)actroy,決定了不同的Adpter。

1.2、創(chuàng)建Converter對(duì)象使用了抽象工廠模式
?? Factory創(chuàng)建同一類的多個(gè)相類似的產(chǎn)品,也避免了在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;
            }
        }
    }

??可以看到每個(gè)工廠可以創(chuàng)建2個(gè)Converter,以GsonConverterFactory為例,一個(gè)工廠創(chuàng)建了GsonRequestBodyConverter和GsonResponseBodyConverter對(duì)象。GsonRequestBodyConverter負(fù)責(zé)將ResponseBody通過Gson轉(zhuǎn)化成ResponType類型。GsonRequestBodyConverter將傳入的java對(duì)象寫入到RequestBody中。

6、適配器模式

??將某個(gè)類的接口轉(zhuǎn)化為客戶端期望的另一個(gè)接口表示,主要的目的是兼容性,讓原本不匹配不能一起工作的兩個(gè)類可以協(xié)同工作。


適配器模式
// 創(chuàng)建
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創(chuàng)建OkhttpCall對(duì)象,并且抽象了adapt方法,這個(gè)方法負(fù)責(zé)請(qǐng)求數(shù)據(jù)。
?? 子類CallAdapted 實(shí)現(xiàn)adapt方法,執(zhí)行Call請(qǐng)求,但是該方法的具體實(shí)現(xiàn)在CallAdapter中的adapt中實(shí)現(xiàn)的。
?? 比如上述的CallAdapter為RxJava2CallAdapter時(shí),執(zhí)行Call請(qǐng)求在RxJava2CallAdapter的adapt方法中,執(zhí)行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轉(zhuǎn)化成泛型T,子類GsonResponseConverter實(shí)現(xiàn)了Convert方法,該類持有TypeAdapter對(duì)象,真正轉(zhuǎn)化是在ObjectTypeAdapter中實(shí)現(xiàn)的。

   // 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轉(zhuǎn)化成需要的對(duì)象,比如DateBean,包轉(zhuǎn)成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、實(shí)現(xiàn)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對(duì)象。

//  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執(zhí)行同步或者異步請(qǐng)求時(shí),調(diào)用createRawCall方法,接著調(diào)用create方法,調(diào)用handlers[p].apply,將參數(shù)設(shè)置給requestBuilder,返回request。

總結(jié)

?? Retrofit使用到了很多模式,除了上述,還使用了比如常見模板設(shè)計(jì)模式,裝飾設(shè)計(jì)模式,原型模式、門面模式、觀察者模式等。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容