Android基础相关

Retrofit源码流程

2021-01-21  本文已影响0人  来lol里

1.介绍和基本使用

Retrofit主要就是为我们定义的接口创造了一个实例,然后这个实例调用接口中的方法将我们定义在注解中的值拼装成发起网络请求所要的信息,最后利用这些信息产生一个我们在接口返回值中规定的对象,这个对象可以用来发起真正的请求,然后会帮我们把网络返回的数据按照我们定义的数据格式做好解析和封装。
简单的讲,Retrofit就是把注解中的东西拼成http请求的对象,然后由这个对象去发起请求。相比Volley省去我们自己去创建Request了,而这部分操作Retrofit其实是通过动态代理的方式帮我们创建出来了。


image.png
//第一步定义api接口
interface WanApi {
   @GET("project/tree/json")
    Call<ProjectBean> getProject();
}
//第二步创建实例
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.wanandroid.com/")
                .addConverterFactory(GsonConverterFactory.create())
                // .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // api接口如果不用call,改用observe的话,这里还可以添加支持RxJava
                .build();
        WanApi getApi = retrofit.create(WanApi.class);

//第三部发起调用
Call<ProjectBean> call = getApi.getProject();
call.enqueue(new Callback<ProjectBean>() {//异步请求
   ......
});

2.源码分析 (版本2.7.2)

从使用上可以看出,核心的部分是在retrofit.create方法开始那么从create方法里可以看到,核心的调用方法是loadServiceMethod

 public <T> T create(final Class<T> service) {
    ...
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
            ...
 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

我们看这个ServiceMethod里到底是个啥,静态方法里就可以看到是其实就是帮我们把请求Request体拼接完整的一些网络参数啊数据之类的一些东西,其实就是将api接口里的一些方法的注解,方法的参数类型,方法参数的注解等信息解析出来

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
     //  解析注解信息,拼装请求参数
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    ······
    // 解析返回数据 Call 或者 Rxjava包装的Call
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }
 //进一步看 RequestFactory.parseAnnotations方法,都是一些具体解析方法

final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
  private final Method method;
  private final HttpUrl baseUrl;
  final String httpMethod;
  private final @Nullable String relativeUrl;
  private final @Nullable Headers headers;
  private final @Nullable MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;
  final boolean isKotlinSuspendFunction;
 ······
  private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
     ····
}
   //下边的进入最后是根据 接口定义的Call 和返回类型ProjectBean 转换我们的Response返回数据,并调用new CallAdapted 
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
    ······
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
   ····· 
    }

最后通过loadServiceMethod(method).invoke方法 ,会调用HttpServiceMethod的invoke方法

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

adapt又会通过DefaultCallAdapterFactory中ExecutorCallbackCall,通过代理okhttp中的call方法,开始网络请求。

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

最后真正的网络数据发起和返回数据的具体解析和转换是在OkhttpCall中进行的。

final class OkHttpCall<T> implements Call<T> {
   ······
   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
        }
      }
    });
  }
上一篇下一篇

猜你喜欢

热点阅读