理解Retrofit

如何使用retrofit

1.引入库

compile 'com.squareup.retrofit2:retrofit:2.0.2'
复制代码

2. 使用流程

retrofit在使用的过程中,需要定义一个接口对象

public @interface ApiService{
    @GET("/users/{username}")
    Call<User> getUser (@Path("username") String username);
    
    @POST
    Call<List<User>> addUser(@Body User user);
}复制代码

3. 创建retrofit实例

Retrofit  retrofit = new Retrofit.Builder()
        .client(OkHttpClient)//配置OKhttp客户端
        .baseUrl("http://www.example.com")
        .addConverterFactory(GsonConverterFactory.create())
        .validateEagerly()  //在Call时,是否立即验证接口中的方法配置
        .callbackExecutor() //回调
        .build();ApiService service = retrofit.create(ApiService.class);
复制代码

4. 创建接口实例

Call<User> user = service.getUser("test");复制代码

5. 发起请求

user.enqueue(new Callback<List<User>>()
        {
            @Override
            public void onResponse(Call<List<User>> call, Response<List<User>> response)
            {
                Log.e(TAG, "normalGet:" + response.body() + "");
            }

            @Override
            public void onFailure(Call<List<User>> call, Throwable t)
            {

            }
        });
复制代码


源码解析

1. 接口实例是如何拿到的

   先来看下build方法,返回了Retrofit实例,参数是传入的值,若没有,使用默认的

public 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> adapterFactories = new ArrayList<>(this.adapterFactories);
  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);
}复制代码


下一步,调用create 发生了什么?

public <T> T create(final Class<T> service) {
  Utils.validateServiceInterface(service); //验证传入的class是否声明为interface
  if (validateEagerly) { //是否立即验证接口中的方法配置,如果true,最终调用loadServiceMethod
      eagerlyValidateMethods(service);
  }

  //如何理解Proxy.newProxyInstance???看后面
  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, 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 serviceMethod = loadServiceMethod(method);
          //返回OkHttpCall对象
          OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
          //最后返回适配以后的Call,比如添加Rxjava适配,则返回Observe对象
          return serviceMethod.callAdapter.adapt(okHttpCall);
        }
      });
}复制代码


2. 如何理解Proxy.newProxyInstance

先看一个例子

public interface ITest{
    @GET("/heiheihei")
    public void add(int a, int b);

}
public static void main(String[] args){
    ITest iTest = (ITest) Proxy.newProxyInstance(ITest.class.getClassLoader(), new Class<?>[]{ITest.class}, new InvocationHandler(){
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
            Integer a = (Integer) args[0];
            Integer b = (Integer) args[1];
            System.out.println("方法名:" + method.getName());
            System.out.println("参数:" + a + " , " + b);

            GET get = method.getAnnotation(GET.class);
            System.out.println("注解:" + get.value());
            return null;
        }
    });
    iTest.add(3, 5);
}
复制代码

运行结果是:

方法名:add
参数:3 , 5
注解:/heiheihei
复制代码

可以看到我们通过Proxy.newProxyInstance产生的代理类,当调用接口的任何方法时,都会调用InvocationHandler#invoke方法,在这个方法中可以拿到传入的参数,注解等。

上面retrofit create的实现中,最后同样使用了Proxy这个类的API,然后在invoke方法里面拿到足够的信息去构建最终返回的Call。

这里一开始没看懂 Proxy.newProxyInstance 作用,参考了blog.csdn.net/lmj62356579…

3. OkHttpCall对象的生成

过程很简单

OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }
复制代码

4. 如何拿到接口方法传入的参数,注解

这一步通过loadServiceMethod  来实现

serviceMethodCache是一个LinkedHashMap,会先从serviceMethodCache缓存里面取,若为NULL则重新构造一个ServiceMethod对象,并返回

private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();

ServiceMethod loadServiceMethod(Method method) {
  ServiceMethod result;
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
      //关键代码,干了什么
      result = new ServiceMethod.Builder(this, method).build();
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}复制代码

下面看下new ServiceMethod.Builder(this, method).build(); 具体工作

//返回接口定义的方法的相关信息
public Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations(); //方法的注解, @GET @POST等
  this.parameterTypes = method.getGenericParameterTypes();//参数类型 
  this.parameterAnnotationsArray = method.getParameterAnnotations(); //参数的注解 @Path @Body等
}复制代码

build的具体工作

public ServiceMethod build() {
  callAdapter = createCallAdapter();  //call的适配, 很重要, 最后由它发起最终请求
  responseType = callAdapter.responseType(); //响应类型
  //...
  responseConverter = createResponseConverter(); //数据转换器

  //关心的重点,开始解析接口定义的方法注解了
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }
  //....

  //参数的注解数量
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    //...
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];

    //解析参数的注解
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }
  //略...
  return new ServiceMethod<>(this);
}复制代码

parseMethodAnnotation(annotation); 把所有你加上的注解及及值提取出来

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);
  }
 //略....
}复制代码


5. http请求是如何发送出去的?

在Retrofit的create方法,最后返回了serviceMethod.callAdapter.adapt(okHttpCall);

这个callAdapter最终拿到的是我们在构建retrofit里面时adapterFactories时添加的,即为:new ExecutorCallbackCall<>(callbackExecutor, call),该ExecutorCallbackCall唯一做的事情就是将原本call的回调转发至UI线程。

public ServiceMethod build() {
  callAdapter = createCallAdapter();  //call的适配, 很重要, 最后由它发起最终请求
  //...
  return new ServiceMethod<>(this);
}复制代码


ServiceMethod.java
private CallAdapter<?> createCallAdapter() {
  Type returnType = method.getGenericReturnType();
  //...
  Annotation[] annotations = method.getAnnotations();
  try {
    return 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);
  }
}复制代码


Retrofit.java
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(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;
    }
  }
 //....
}复制代码

最后调用ExecutorCallAdapterFactory的get方法

@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  final Type responseType = Utils.getCallResponseType(returnType);
  return new CallAdapter<Call<?>>() {
    @Override public Type responseType() {
      return responseType;
    }
    
    //调用它
    @Override public <R> Call<R> adapt(Call<R> call) {
      return new ExecutorCallbackCall<>(callbackExecutor, call);
    }
  };
}复制代码


可以看到adapt返回的是ExecutorCallbackCall对象,继续往下看:

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);
          }
        });
      }
    });
  }
}复制代码

可以看出ExecutorCallbackCall仅仅是对Call对象进行封装,类似装饰者模式,只不过将其执行时的回调通过callbackExecutor进行回调到UI线程中去了。

其实我们在写代码时拿到的call对象就是ExecutorCallbackCall对象,最后一般会执行enqueue方法,看下具体实现

@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);
          }
        });
      }
    });
  }复制代码

delegate就是构建ExecutorCallbackCall时传入的OkHttpCall对象,因此会调用OkHttpCall的enqueue,看下实现

@Override public void enqueue(final Callback<T> callback) {
  if (callback == null) throw new NullPointerException("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 {
        call = rawCall = createRawCall();
      } catch (Throwable 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)
        throws IOException {
      Response<T> response;
      try {
        response = parseResponse(rawResponse);
      } catch (Throwable e) {
        callFailure(e);
        return;
      }
      callSuccess(response);
    }

    @Override public void onFailure(okhttp3.Call call, IOException e) {
      try {
        callback.onFailure(OkHttpCall.this, e);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }

    private void callFailure(Throwable e) {
      try {
        callback.onFailure(OkHttpCall.this, e);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }

    private void callSuccess(Response<T> response) {
      try {
        callback.onResponse(OkHttpCall.this, response);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }
  });
}复制代码

整个流程就是创建okhttp3.Call对象,并进一步调用其enqueue方法,okhttp3.Call的创建通过

createRawCall方法

private okhttp3.Call createRawCall() throws IOException {
  Request request = serviceMethod.toRequest(args);
  okhttp3.Call call = serviceMethod.callFactory.newCall(request);
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}复制代码

可以看到,通过serviceMethod.toRequest实现了ServiceMethod到Request的转换,接着通过request去构造call对象,然后返回.


构建Request的过程很简单,就是把从把从ServiceMethod得到的参数传入RequestBuilder和RequestBody


还有一个问题是,对于网络返回的数据怎么转换成我们想要的类型?

同样在okhttp3.Call中enqueue的请求成功回调中  parseResponse(rawResponse)

call.enqueue(new okhttp3.Callback() {
  @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
      throws IOException {
    Response<T> response;
    try {
      response = parseResponse(rawResponse);
    } catch (Throwable e) {
      callFailure(e);
      return;
    }
    callSuccess(response);
  }复制代码

parseResponse方法实现

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) {
    return Response.success(null, rawResponse);
  }

  ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
  try {
    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;
  }
}复制代码

可以看到最后通过serviceMethod对ResponseBody进行转化,然后返回,转化实际上就是通过responseConverter的convert方法。

ServiceMethod.java
/** Builds a method return value from an HTTP response body. */
T toResponse(ResponseBody body) throws IOException {
  return responseConverter.convert(body);
}复制代码


6. Converter.Factory

 Converter.Factory用于将返回的数据解析成指定的类型,基本使用如下

Retrofit retrofit = new Retrofit.Builder()
    .addConverterFactory(GsonConverterFactory.create())
        .build();
复制代码

GsonConverterFactory需要引入,它是Converter.Factory factory对象的具体实现

compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:converter-gson:2.0.2';
复制代码


看下Converter.Factory factory源码

public interface Converter<F, T> {
  T convert(F value) throws IOException;

  /** Creates {@link Converter} instances based on a type and target usage. */
  abstract class Factory {
    /**
     * Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for
     * response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>}
     * declaration.
     */
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }

    /**
     * Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
     * values.
     */
    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }

    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
  }复制代码


Factory是个抽象类,有三个非抽象方法,我们自定义时可以根据需要选择实现。

下面看下squareup官方的GsonConverterFactory的实现

public final class GsonConverterFactory extends Converter.Factory {
 
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}复制代码


看着挺简单的。。。以后再写

7.总结

  • 首先构造retrofit实例,根据需要传入baseurl,callFactory, client(默认okhttpclient),converterFactories,adapterFactories,excallbackExecutor。
  • 然后通过create方法拿到接口的实现类
  • 调用接口方法时,进入Proxy的invoke方法内部,拿到我们所声明的注解以及实参等,构造ServiceMethod,ServiceMethod中解析了大量的信息,最痛可以通过toRequest构造出okhttp3.Request对象。有了okhttp3.Request对象就可以很自然的构建出okhttp3.call,最后calladapter对Call进行装饰返回。
  • 拿到Call就可以执行enqueue或者execute方法了


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值