retrofit学习

介绍

准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。 原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装

在这里插入图片描述

App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求 参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作。
在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用 户的需求对结果进行解析。

使用

Retrofit 请求的样例代码

 		//step1
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.wanandroid.com/")
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                .build();
        //step2
        ISharedListService sharedListService = retrofit.create(ISharedListService.class);
        //step3
        Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2,1);
        //step4 
        sharedListCall.enqueue(new Callback<SharedListBean>() {
            @Override
            public void onResponse(Call<SharedListBean> call, Response<SharedListBean> response{
                if (response.isSuccessful()) { System.out.println(response.body().toString());
                }
            }
            @Override 
            public void onFailure(Call<SharedListBean> call, Throwable t) { t.printStackTrace();
            } 
        }

Step1: 创建retrofit对象, 构建一个网络请求的载体对象,和okhttp构建OkhttpClient对象有一样的意义,只不过retrofit在build的时候有非常多的初始化内容,这些内容可以为后面网络请求提供准备,如准备 现成转换Executor,Gson convert,RxJavaCallAdapter。

Step2:Retrofit的精髓,为统一配置网络请求完成动态代理的设置。

Step3:构建具体网络请求对象Request(service),在这个阶段要完成的任务:
1)将接口中的注解翻译成对应的参数;
2)确定网络请求接口的返回值response类型以及对应的转换器;
3)讲Okhttp的Request封装成为Retrofit的OKhttpCall。
总结来说,就是根据请求service 的Interface来封装Okhttp请求Request。
Step4:后面就进行网络请求了,然后处理网络请求的数据了

对网络请求数据的封装

  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);
            //封装一个OKhttp的call,扔到adapt中
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

判断缓存是否存在,如果不存在则进行读取

 private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

loadServiceMethod(method);将接口中的注解和baseUrl结合形成完整的方法拼接并缓存起来
总共有23中类型,逻辑都是一样的,从get和post我们经常用的看就差不多了。

基本上都是注解、动态代理、反射的应用,这里就不专门讲了,后面有时间专门写一篇介绍。
也就是说这里得到的已经是动态代理的对象,下一步调用对应的请求方法就能成功执行网络请求,那么前面所有的封装都在build里面了。

封装OKHTTP call

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.wanandroid.com/")
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                .build();

添加URL这个很容易理解,添加的这些ConverterFactory具体作用体现在哪,而且可以添加多种。
1: 成功建立一个Retrofit对象的标准:
配置好Retrofit类里的成员变量
baseUrl:网络请求的url地址
callFactory:网络请求工厂
callbackExecutor:回调方法执行器
adapterFactories:网络请求适配器工厂的集合
converterFactories:数据转换器工厂的集合

  public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      //网络请求直接默认就是okhttp
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
		
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
      	//它的实现类在本身的静态类Android下面,就是一个主线程的handler
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      //创建一个adapter的集合,如果你没有主动添加的话默认就是一个线程切换的adapter
      //也就是上面我们创建的主线程的handler
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

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

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

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

先按照正常情况下我们只有一个defaultCallAdapterFactory分析,它接收了上面创建的OkHttpClient,这个OkHttpClient实现了 okhttp3.Call.Factory ,我们最终调用网络请求不就是 okhttp3.Call.Factory 的实现类去调用它的同步异步方法,但是现在我们是在build方法里,目前才实例化了这个类,这个类里面的信息是空白的。

在上面调用create返回代理对象的时候,下步调用代理方法,在代理方法里面:

  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.adapt(okHttpCall);
          }
        });
 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);

okHttpCall这个是有实际参数的call, serviceMethod.adapt(okHttpCall);返回我们最终需要的可以调用okhttp方法的call,跟进去。

T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

再跟进CallAdapter,它是个接口,有三个默认实现类。
在这里插入图片描述
很明显,我们上面在build方法里默认添加的是ExecutorCallAdapterFactory类。

它的adaptger方法,接收一个call,并把自己持有的callbackExecutor丢进去。

 @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }

我们看下这个类的大概作用,实现了call,构造函数接收一个call,
真正的实现方法是接收进来的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);
            }
          });
        }
      });
    }
  callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });

这里是okhttp的call请求完网络之后, callbackExecutor就是我们默认加入的主线程handler。
这也解释了为什么retrofit运行完返回是在主线程了。

如果我在build的时候添加了Gson转换器和Rxjava的adapter,它是如何拿到的。

OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

args只是代理对象方法的参数,那么我们build的时候加入的所有对象都在serviceMethod里面了,
而serviceMethod也是通过build创建出来的。

 public ServiceMethod build() {
 		//拿到我们设置的adapter
      callAdapter = createCallAdapter();
      //拿到返回值对象
      responseType = callAdapter.responseType();
      ...

类型靠反射得到

Type returnType = method.getGenericReturnType();

从build的时候创建的集合里面拿,包括数据转换器也是一样逻辑的代码。

  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

返回数据的封装

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

delegate.enqueue最外层的回调是我们用户层调用的回调,里面一层callbackExecutor.execute是默认adapter的回调回主线程的回调。
callback.onFailure是OKhttpCall的回调,ExecutorCallbackCall是call本身的回调。
它是什么时候转换成我们需要的泛型的呢?OkHttpCall的回调如下

     @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
        	//数据转换
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
  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里面的方法,而我们配置的Gson解析就在里面了
      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;
    }
  }

如果上面的adapter里面不是默认转换回主线程的,而是我们配置的RxJava2CallAdapterFactory,
对应的就会回调到对应的实现类里。
基本上就是build的时候创建添加,create方法的时候获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值