当前位置: 首页 > article >正文

Android-retrofit源码解析

目录

一,前言

二,使用

三,源码分析


一,前言

retrofit是目前比较流行的网络框架,但它本身并没有网络请求的功能,网络请求的功能是由okhttp来完成的。retrofit只是负责网络请求接口的封装,让我们更加方便的请求网络。

在对retrofit框架进行了解之前,我们需要先了解okhttp,另外retrofit涉及到的设计模式很多,我们主要要了解动态代理模式和适配器模式。

Android-okhttp详解-CSDN博客

Java 代理模式之静态代理与动态代理_java静态代理模式-CSDN博客

Android设计模式--适配器模式_android 适配器模式-CSDN博客

二,使用

在build.gradle配置引用:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

创建数据类:

data class ArticleBean (
    val chapterName :String,
    val link :String
)

创建请求接口:

interface YzTestService {

    @GET("article/list/0/{name}")
    fun yzTest(@Path("name") name:String?): Call<List<ArticleBean>>
}

在activity使用:

class CommonActivity : AppCompatActivity() {

    var url = "https://www.wanandroid.com"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_common)
        
        val retrofit =Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        val service =retrofit.create(YzTestService::class.java)

        val repos:Call<List<ArticleBean>> = service.yzTest("json")

        repos.enqueue(object :Callback<List<ArticleBean>>{
            override fun onResponse(call: Call<List<ArticleBean>>, response: Response<List<ArticleBean>>) {
                Log.d("yz","请求成功:"+response.body().toString())
            }

            override fun onFailure(call: Call<List<ArticleBean>>, t: Throwable) {
                Log.d("yz","请求失败:"+t.toString())
            }

        })
    }
}

三,源码分析

分析源码一般是从使用入手,一般是着眼于最核心的代码。

从使用分析,我们先看repos.enqueue它的源码:

void enqueue(Callback<T> callback);

结果是个抽象方法,所以我们继续往上看它的使用service.yzTest("json"),这个是我们自己创建的,然后接着往上看retrofit.create(YzTestService::class.java)的源码:

public <T> T create(final Class<T> service) {
  //判断是否接口 不是接口抛出异常
  validateServiceInterface(service);
  return (T)
    //动态代理模式
      Proxy.newProxyInstance(
            //第一个参数 任意的类加载器
          service.getClassLoader(),
            //第二个参数 传入的service的class对象
          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(method)这个方法:

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;
}

接着继续看ServiceMethod.parseAnnotations(this, method)这个方法:

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //获取方法的注解信息等 创建请求工厂 里面包含请求的url,请求方式,请求参数等等
  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);
}

如果符合判断条件,则走HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)

看看这个类:

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT>

它继承了ServiceMethod这个类,我们在看loadServiceMethod(method).invoke(args)的invoke的方法时,发现它是ServiceMethod的抽象方法,然后我们又看到了HttpServiceMethod这个类继承了ServiceMethod,所以我们在HttpServiceMethod这个类里面找一下invoke这个方法,它就是ServiceMethod的具体实现:

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

然后看它的adapt方法:

protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

它是HttpServiceMethod的一个抽象方法,所以我们只能倒回去看 OkHttpCall这个类:

final class OkHttpCall<T> implements Call<T>

发现它是继承了Call,就是上面我们说的:

void enqueue(Callback<T> callback);

这个抽象方法。

所以我们看看OkHttpCall这个类里面enqueue这个方法的具体实现:

@Override
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 {
        //创建okhttp3的Call
        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
          }
        }
      });
}

上面的代码都很简单,主要就是创建了一个okhttp3的Call,并用这个Call对象去请求网络

创建对象的代码为:

call = rawCall = createRawCall();

还有一个主要方法就是:

response = parseResponse(rawResponse);

这行代码主要就是解析返回的数据。具体代码比较简单,就是数据的具体解析。这里就不做具体分析了。

最重要的方法就是:

callback.onResponse(OkHttpCall.this, response);

callback.onFailure(OkHttpCall.this, e);

这两个回调就是我们使用的回调。这样整个流程就通了。

看完主线之后,再来看看上面没有看的HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)这个方法:

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
  boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
  boolean continuationWantsResponse = false;
  boolean continuationBodyNullable = false;
  Annotation[] annotations = method.getAnnotations();
  Type adapterType;
//判断是否支持kotlin挂起方法
  if (isKotlinSuspendFunction) {
    Type[] parameterTypes = method.getGenericParameterTypes();
    Type responseType =
        Utils.getParameterLowerBound(
            0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
    if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
      // Unwrap the actual body type from Response<T>.
      responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
      continuationWantsResponse = true;
    } else {
      // TODO figure out if type is nullable or not
      // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
      // Find the entry for method
      // Determine if return type is nullable or not
    }
    adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
    annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
  } else {
    adapterType = method.getGenericReturnType();
  }
// 关键代码 创建CallAdapter
  CallAdapter<ResponseT, ReturnT> callAdapter =
      createCallAdapter(retrofit, method, adapterType, annotations);
  Type responseType = callAdapter.responseType();
  if (responseType == okhttp3.Response.class) {
    throw methodError(
        method,
        "'"
            + getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  if (responseType == Response.class) {
    throw methodError(method, "Response must include generic type (e.g., Response<String>)");
  }
  // TODO support Unit for Kotlin?
  if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
    throw methodError(method, "HEAD method must use Void as response type.");
  }
  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  if (!isKotlinSuspendFunction) {
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
  } else if (continuationWantsResponse) {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>)
        new SuspendForResponse<>(
            requestFactory,
            callFactory,
            responseConverter,
            (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
  } else {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>)
        new SuspendForBody<>(
            requestFactory,
            callFactory,
            responseConverter,
            (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
            continuationBodyNullable);
  }
}

从上面的代码中我们提取出一个关键代码:createCallAdapter,来看看它的源码:

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
    Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
  try {
    //noinspection unchecked
    return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(method, e, "Unable to create call adapter for %s", returnType);
  }
}

接着往下看retrofit.callAdapter:

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}


public CallAdapter<?, ?> nextCallAdapter(
    @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
  Objects.requireNonNull(returnType, "returnType == null");
  Objects.requireNonNull(annotations, "annotations == null");
  int start = callAdapterFactories.indexOf(skipPast) + 1;
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
      return adapter;
    }
  }
  StringBuilder builder =
      new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");
  if (skipPast != null) {
    builder.append("  Skipped:");
    for (int i = 0; i < start; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    builder.append('\n');
  }
  builder.append("  Tried:");
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
  }
  throw new IllegalArgumentException(builder.toString());
}

这里面没有什么有用的代码 关键就是callAdapterFactories.get(i).get(returnType, annotations, this);这个方法,我们先看下callAdapterFactories是什么:

final List<CallAdapter.Factory> callAdapterFactories;

再看下它在哪里赋值的:

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);
}

这个就是在我们使用的时候,调用Retrofit.build方法的时候,赋值的。

具体看下它的赋值内容:

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));

因为我们是android平台 所以我们直接查看platform.defaultCallbackExecutor()找android平台就能看到它的具体实现:

@Override
public Executor defaultCallbackExecutor() {
  return new MainThreadExecutor();
}
static final class MainThreadExecutor implements Executor {
  private final Handler handler = new Handler(Looper.getMainLooper());
  @Override
  public void execute(Runnable r) {
    handler.post(r);
  }
}

这个就是切换到了主线程。

然后我们回到上面看看callAdapterFactories.get(i).get(returnType, annotations, this);的方法:

@Override
public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  if (!(returnType instanceof ParameterizedType)) {
    throw new IllegalArgumentException(
        "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
  }
  final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
  final Executor executor =
      Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
          ? null
          : callbackExecutor;
  return new CallAdapter<Object, Call<?>>() {
    @Override
    public Type responseType() {
      return responseType;
    }
    @Override
    public Call<Object> adapt(Call<Object> call) {
      return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
    }
  };
}

然后我们就发现了adapt方法,我们回到前面的代码:

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

这个里面的adapt就是上面的adapt,它把OKHttpcall又包了一层,具体看看怎么包装的:

static final class ExecutorCallbackCall<T> implements Call<T> {
  final Executor callbackExecutor;//传入的android平台的executor 用于切换主线程
  final Call<T> delegate; //OKHttpCall
  ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
  }
  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");
    delegate.enqueue(
        new Callback<T>() {
          @Override
          public void onResponse(Call<T> call, final Response<T> response) {
            //请求完成之后 切换到主线程
            callbackExecutor.execute(
                () -> {
                  if (delegate.isCanceled()) {
                    // Emulate OkHttp's behavior of throwing/delivering an IOException on
                    // cancellation.
                     //调用者传入的callback
                    callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                  } else {
                    //调用者传入的callback
                    callback.onResponse(ExecutorCallbackCall.this, response);
                  }
                });
          }
          @Override
          public void onFailure(Call<T> call, final Throwable t) {
            callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
          }
        });
  }
  @Override
  public boolean isExecuted() {
    return delegate.isExecuted();
  }
  @Override
  public Response<T> execute() throws IOException {
    return delegate.execute();
  }
  @Override
  public void cancel() {
    delegate.cancel();
  }
  @Override
  public boolean isCanceled() {
    return delegate.isCanceled();
  }
  @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
  @Override
  public Call<T> clone() {
    return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
  }
  @Override
  public Request request() {
    return delegate.request();
  }
  @Override
  public Timeout timeout() {
    return delegate.timeout();
  }
}

这样就在内部结果返回时自动切换到了主线程,避免了用户自己切换线程的麻烦。


http://www.kler.cn/a/534319.html

相关文章:

  • Pytest+selenium UI自动化测试实战实例
  • 【NLP 20、Encoding编码 和 Embedding嵌入】
  • QT:信号和槽
  • Java BIO详解
  • LeetCode 0922.按奇偶排序数组 II:O(1)空间复杂度-一次遍历双指针
  • kubernetes 高可用集群搭建
  • C语言基础系列【3】VSCode使用
  • golang开发技能
  • 【starrocks学习】之将hive表数据同步到starrocks
  • MySQL面试题----如何进行 MySQL 数据库备份与恢复
  • 2025 持续防范 GitHub 投毒,通过 Sharp4SuoExplorer 分析 Visual Studio 隐藏文件
  • 下面是一个简单的C++词法分析器示例
  • Unity3D学习笔记(二)
  • 网络设备的安全加固
  • HAL库 Systick定时器 基于STM32F103EZT6 野火霸道,可做参考
  • Rapidjson 实战
  • Spring @EventListener 注解:让应用更加模块化和可扩展
  • Java面试题基础篇2:10道基础面试题
  • Docker深度解析:容器与容器局域网
  • 5-Scene层级关系
  • 机器学习--python基础库之Matplotlib (2) 简单易懂!!!
  • 【centOS】安装docker环境,替换国内镜像
  • 分布式光伏监控解决方案-并网柜保护装置
  • gym-anytrading
  • 作业二.自定义数据集使用scikit-learn中的包实现线性回归方法对其进行拟合
  • 算法--最长回文子串