软件编程
位置:首页>> 软件编程>> Android编程>> Android Retrofit原理深入探索

Android Retrofit原理深入探索

作者:明智的健哥  发布时间:2023-09-06 02:47:15 

标签:Android,Retrofit

序章

首先引入依赖

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

在原理之前,我们先来回忆一下Retrofit的基本使用

1、定义接口

interface MyService {
   @GET("gallery/{imageType}/response")
   fun getImages(@Path("imageType") imageType: String): Call<List<String>>
}

2、构建Retrofit,创建网络请求接口类实例

val retrofit = Retrofit.Builder()
           .baseUrl(BASE_URL)
           .build()
       val myService = retrofit.create(MyService::class.java)

3、生成Call,执行请求

val resp = myService.getImages("banner")
       resp.enqueue(object : Callback<List<String>> {
           override fun onResponse(call: Call<List<String>>, response: Response<List<String>>) {
               TODO("Not yet implemented")
           }
           override fun onFailure(call: Call<List<String>>, t: Throwable) {
               TODO("Not yet implemented")
           }
       })

这样一个基本的网络请求就搞定了,使用很简洁,正是因为其内部使用了大量的设计模式和优秀的架构设计,才得以使其如此方便地进行网络请求,下面我们就一起来探索探索Retrofit的设计之美。

Retrofit构建过程

使用了建造者模式通过内部静态类Builder构建一个Retrofit实例,这里只列出了部分方法,其他类似

public static final class Builder {
   private final Platform platform;
   // 网络请求工厂,工厂方法模式
   private @Nullable okhttp3.Call.Factory callFactory;
   // 网络请求地址
   private @Nullable HttpUrl baseUrl;
   // 数据转换器工厂的集合
   private final List<Converter.Factory> converterFactories = new ArrayList<>();
   // 网络请求适配器工厂的集合,默认是ExecutorCallAdapterFactory
   private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
   // 回调方法执行器,用于切换线程
   private @Nullable Executor callbackExecutor;
   // 一个开关,为true则会缓存创建的ServiceMethod
   private boolean validateEagerly;
   //......
   public Builder baseUrl(String baseUrl) {
     Objects.requireNonNull(baseUrl, "baseUrl == null");
     return baseUrl(HttpUrl.get(baseUrl));
   }
   public Builder baseUrl(HttpUrl baseUrl) {
     Objects.requireNonNull(baseUrl, "baseUrl == null");
     List<String> pathSegments = baseUrl.pathSegments();
     if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
       throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
     }
     this.baseUrl = baseUrl;
     return this;
   }
   // 将一个含有Gson对象实例的GsonConverterFactory放入数据转换器工厂
   public Builder addConverterFactory(Converter.Factory factory) {
     converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
     return this;
   }
   //......
}

通过build,我们上面Builder类中的参数对象都配置到了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();
     }
     Executor callbackExecutor = this.callbackExecutor;
     if (callbackExecutor == null) {
       callbackExecutor = platform.defaultCallbackExecutor();
     }
     // Make a defensive copy of the adapters and add the default Call adapter.
     List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
     callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
     // Make a defensive copy of the converters.
     List<Converter.Factory> converterFactories =
         new ArrayList<>(
             1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
     // Add the built-in converter factory first. This prevents overriding its behavior but also
     // ensures correct behavior when using converters that consume all types.
     converterFactories.add(new BuiltInConverters());
     converterFactories.addAll(this.converterFactories);
     converterFactories.addAll(platform.defaultConverterFactories());
     return new Retrofit(
         callFactory,
         baseUrl,
         unmodifiableList(converterFactories),
         unmodifiableList(callAdapterFactories),
         callbackExecutor,
         validateEagerly);
   }

创建网络请求接口实例过程

使用 * 的方式拿到所有注解配置后,创建网络请求接口实例。

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 {
               // If the method is a method from Object then defer to normal invocation.
               if (method.getDeclaringClass() == Object.class) {
                 return method.invoke(this, args);
               }
               args = args != null ? args : emptyArgs;
               return platform.isDefaultMethod(method)
                   ? platform.invokeDefaultMethod(method, service, proxy, args)
                   : loadServiceMethod(method).invoke(args);
             }
           });
 }

跟踪 loadServiceMethod,parseAnnotations解析注解配置得到ServiceMethod,然后加入到serviceMethodCache缓存中,是一个ConcurrentHashMap。

ServiceMethod<?> loadServiceMethod(Method method) {
   ServiceMethod<?> result = serviceMethodCache.get(method);
   if (result != null) return result;
   synchronized (serviceMethodCache) {
     result = serviceMethodCache.get(method);
     if (result == null) {
       result = ServiceMethod.parseAnnotations(this, method);
       serviceMethodCache.put(method, result);
     }
   }
   return result;
 }
abstract class ServiceMethod<T> {
 static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
   RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
   Type returnType = method.getGenericReturnType();
   if (Utils.hasUnresolvableType(returnType)) {
     throw methodError(
         method,
         "Method return type must not include a type variable or wildcard: %s",
         returnType);
   }
   if (returnType == void.class) {
     throw methodError(method, "Service methods cannot return void.");
   }
   return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
 }
 abstract @Nullable T invoke(Object[] args);
}

执行请求过程

public void enqueue(final Callback<T> callback) {
   Objects.requireNonNull(callback, "callback == null");
   okhttp3.Call call;
   Throwable failure;
   synchronized (this) {
     if (executed) throw new IllegalStateException("Already executed.");
     executed = true;
     call = rawCall;
     failure = creationFailure;
     if (call == null && failure == null) {
       try {
         // 创建一个OkHttp的Request对象请求
         call = rawCall = createRawCall();
       } catch (Throwable t) {
         throwIfFatal(t);
         failure = creationFailure = t;
       }
     }
   }
   if (failure != null) {
     callback.onFailure(this, failure);
     return;
   }
   if (canceled) {
     call.cancel();
   }
   call.enqueue(
       new okhttp3.Callback() {
         @Override
         public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
           Response<T> response;
           try {
             // 解析网络请求返回的数据
             response = parseResponse(rawResponse);
           } catch (Throwable e) {
             throwIfFatal(e);
             callFailure(e);
             return;
           }
           try {
             callback.onResponse(OkHttpCall.this, response);
           } catch (Throwable t) {
             throwIfFatal(t);
             t.printStackTrace(); // TODO this is not great
           }
         }
         @Override
         public void onFailure(okhttp3.Call call, IOException e) {
           callFailure(e);
         }
         private void callFailure(Throwable e) {
           try {
             callback.onFailure(OkHttpCall.this, e);
           } catch (Throwable t) {
             throwIfFatal(t);
             t.printStackTrace(); // TODO this is not great
           }
         }
       });
 }
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
   ResponseBody rawBody = rawResponse.body();
   // Remove the body's source (the only stateful object) so we can pass the response along.
   rawResponse =
       rawResponse
           .newBuilder()
           .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
           .build();
   int code = rawResponse.code();
   // 根据响应返回的状态码进行处理
   if (code < 200 || code >= 300) {
     try {
       // Buffer the entire body to avoid future I/O.
       ResponseBody bufferedBody = Utils.buffer(rawBody);
       return Response.error(bufferedBody, rawResponse);
     } finally {
       rawBody.close();
     }
   }
   if (code == 204 || code == 205) {
     rawBody.close();
     return Response.success(null, rawResponse);
   }
   ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
   try {
     // 将响应体转为Java对象
     T body = responseConverter.convert(catchingBody);
     return Response.success(body, rawResponse);
   } catch (RuntimeException e) {
     // If the underlying source threw an exception, propagate that rather than indicating it was
     // a runtime exception.
     catchingBody.throwIfCaught();
     throw e;
   }
 }

来源:https://blog.csdn.net/qq_45485851/article/details/122257801

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com