Jmeter 控制跳转 redux jtable bower alertifyjs 传智播客python change事件 jquery使用ajax spark文档 android调试工具 maven配置eclipse mysql时间戳转日期 centos定时任务 python学习 python取随机数 windows安装python环境 python支持中文 python入门例子 python安装程序 python学习方法 java连接mysql java单继承 java将数据写入文件 java格式化字符串 销售单软件 stretchcolumns java核心技术 flash基础 js保留两位小数 java字符串截取 迅雷会员共享账号 pr加速视频 bin文件编辑器 qq游戏黑名单 凯立德下载 轮播图代码 极速pdf转word 文字转音频软件 机械键盘光轴
当前位置: 首页 > 学习教程  > 编程语言

retrofit源码解析

2020/12/28 18:32:19 文章标签:

准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。 原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装 App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求 …

准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。

原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装

App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求 参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作。

在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用 户的需求对结果进行解析。

一、整体架构分析

4

注意:

create的过程里没有使用动态代理

整体的架构就是

1、对网络参数的封装(协议、表单、restful)

2、封装Okhttp

3、数据结果封装

代码实例的创建过程

   Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("WWW.BAIDU.COM")
                .addConverterFactory(AAA)
                .build();
        retrofit.create(new classService);

成功建立一个Retrofit对象的标准:配置好Retrofit类里的成员变量

1、baseUrl:网络请求的url地址

不多解释这个


2、callFactory:网络请求工厂

首先我们看一下初始化的build方法

retrofit是一个build的构建者设计模式,一般使用建造者模式,在构造函数里面有4-5个函数,且有可选参数,可以使用构造者模式来进行

retrofit本身是门面设计模式,对外的都是通过Retrofit来展示,内部封装了okhttp

build构建了一个okhttpclient,此处虽然是工厂模式,但是实际上默认用的就是okhttp,所以只支持okhttp

 public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
     
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        //看此处。构建了一个okhttpclient
        callFactory = new OkHttpClient();
      }
       //线程管理器
//platform就是android平台
      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> adapterFactories = new ArrayList<>(this.adapterFactories);
//添加一个默认的adapter
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

Executor 是一个线程管理器。platfrom就是一个android平台,里面封装了主线程的handler,讲消息封装至主线程执行

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
//切换主线程,post发送
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

添加一个默认的adapter   defaultCallAdapterFactory,把okhttp转变成retrofit的

  CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }

  CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }

扩展:现在我们看一下create里的方法,产生了一个OkHttpCall,并封装返回了一个okhttp的adapter封装,

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public 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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

这里传进有什么用呢?就和下边adapt交相呼应,将okhttpcall封装了,ExecutorCallbackCall是封装后的类,带有同步异步各种请求,是对okhttp的封装

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, 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) {
      checkNotNull(callback, "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);
            }
          });
        }
      });
    }

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

回到我们之前的思路,就是封装了okhttp的封装,如果传入的不是默认的adapter,如果我们用的是rxjava,我么就可以将okhttp封装成obseverble;

converterFactories就是将okhttp的参数转换成retrofit的参数,可以在初始化的时候自己定义转换的方式,一般我们使用gson

  public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

至此,build构建过程完成了,看一下下面的流程,做了下面的一些事情

 

然后、创建了一个ISharedListService 接口类的对象,create函数内部使用了动态代理来创建接口对象,这样的设计可以让所有的访问请求都被代理

\

Call sharedListCall = sharedListService.getSharedList(2,1);

调用getSharedList的时候,在动态代理里面,会存在一个函数 getSharedList,这个函数里面会调 用 invoke,这个invoke函数也就是retrofit里面 invoke函数。所以,动态代理可以代理所有的接口,让所有的接口都走 invoke函数,这样就可以拦截调用函数 的执行,从而将网络接口的参数配置归一化。

实现原理和这个差不多,都是在create里面动态代理实现监听封装。执行invoke函数就会拦截,使用serviceMethod来进行处理

反射+注解+retrofit+okhttp3总结

在这里,默认是封装成了ExecutorCallbackCall,使用adapt方法

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public 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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

难点就在与loadServiceMethod进行参数适配,里面使用了缓存,为了减少反射产生的性能影响

  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

在nextCallAdapter里面可以看见这里是要从adapterFactories里面获取我们需要的adapter封装类,根据retrunType来看是哪一个adapter,这个是反射获取的,记得吗,我们事有一个默认的

  final class ServiceMethod<R, T> {
...

     public ServiceMethod build() {
      callAdapter = createCallAdapter();
    }
...
private CallAdapter<T, R> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

}


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

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
  public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

然后在serviceMethod的build的方法进行反射解析,不详细解释了

 for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

至此完成了这个操作,下面那个红色的圈内就是这么实现的

3、callbackExecutor:回调方法执行器

接下来我们可以利用create生辰的api类,可以执行enqueue方法,这个方法会调用默认的adapter里面,也就是封装的ExecutorCallbackCall

delegate是之前在动态代理里面调用反射,使用adapt传过来的OkHttpCall,是对okhttp3的封装,所以这里也是使用OkHttpCall的方法,然后调用okhttp的enqueque

okhttp3具体原理看这里

 @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "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);
            }
          });
        }
      });
    }

回调之后,就会回调到最上层使用,这里面加入了线程切换

callbackExecutor.execute

在build里面传归来的,实际上就是PlatForm里面的线程切换

rxjava线程切换看这里、其实这里并不算是rxjava的切换,而是handler的主线程切换

  static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

至此。请求、封装、回调调用完成


4、adapterFactories:网络请求适配器工厂的集合

5、converterFactories:数据转换器工厂的集合

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

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
///看这里,又调用了servicemethod的方法进行传还
      T body = serviceMethod.toResponse(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;
    }
  }

 T body = serviceMethod.toResponse(catchingBody);、

在okHttpCall里面,调用了serviceMethod。为什么要用这个呢,因为所有的转换器保存在retrofit里面,然后create的时候,servicemethod获得了其引用,并在内部可以获取到我们之前传入的转换器

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


本文链接: http://www.dtmao.cc/news_show_550000.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?