Retrofit基本介绍

Retrofit是Square开源的一个适用于Android和Java的类型安全的HTTP网络框架。其本质是对OKHttp的进一步封装,通过接口的方式进行网络请求,结合了注解、动态代理等技术实现模块解耦,简化了网络请求的上层逻辑。从Android4.4开始,http的底层实现已替换成了OKHttp,Retrofit也因此成为了Android平台上主流的网络框架之一。

http://square.github.io/retro...

Retrofit使用方法

Step1:声明Retrofit API请求接口

    public interface GitHub {        @GET("/repos/{owner}/{repo}/contributors")        Call> contributors(            @Path("owner") String owner,            @Path("repo") String repo);    }
  • 请求类型:以@GET/POST/PUT/DELETE注解声明
  • 请求相对URL:以请求方法注解内的Value值表示
  • 请求参数:以接口方法@Path参数表示

Step2:构建Retrofit对象并创建API接口实例

    // Create a very simple REST adapter which points the GitHub API.    Retrofit retrofit = new Retrofit.Builder()        .baseUrl("https://api.github.com")        .addConverterFactory(GsonConverterFactory.create())        .build();    // Create an instance of our GitHub API interface.    GitHub github = retrofit.create(GitHub.class);
  • 通过baseUrl接口声明接口请求域名;
  • 配置对象的序列化和反序列化转换工厂;

Step3:通过API接口方法创建Call实例并发起请求

    // Create a call instance for looking up Retrofit contributors.    Call> call = github.contributors("square", "retrofit");    // Fetch and print a list of the contributors to the library.    List contributors = call.execute().body();

Retrofit的实现就是这么简单优雅,业务层只需要像调用普通接口一样即可完成网络请求。

Retrofit源码解析

首先要构建一个Retrofit实例,其作用是把接口方法注解转换为OKHttp请求。

Retrofit.Builder.build

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 callAdapterFactories = new ArrayList<>(this.callAdapterFactories);      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));      // Make a defensive copy of the converters.      List 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);    }  }
  • callFactory,生产并处理请求的工厂(默认创建OKHttpClient)
  • callbackExecutor,用以处理callback线程调度(Android默认回调到主线程)
  • callAdapterFactories,用以生产CallAdapter以处理Response类型转换(默认使用ExecutorCallAdapterFactory)
  • converterFactories,用以生产Converter处理http请求响应的数据转换(默认使用BuiltInConverters)
Retrofit实例化完成,创建API接口动态代理实现。

Retrofit.create

public  T create(final Class 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 serviceMethod =                (ServiceMethod) loadServiceMethod(method);            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);            return serviceMethod.adapt(okHttpCall);          }        });  }  
  • serviceMethod,负责把接口方法注解转换为http表示(包括httpMethod/header/body/url等)
  • okHttpCall,负责把serviceMethod转换为okhttp3.Call,并且包装了okhttp3.Call的接口调用。
  • serviceMethod.adapt:负责把OKHttpCall转为ExecutorCallbackCall,使其具备线程调度能力。
接口动态代理创建完成,开始执行网络请求。

OKHttpCall.execute

    @Override     public Response execute() throws IOException {        okhttp3.Call call;        synchronized (this) {            if (executed) throw new IllegalStateException("Already executed.");            executed = true;            if (creationFailure != null) {                if (creationFailure instanceof IOException) {                    throw (IOException) creationFailure;                } else if (creationFailure instanceof RuntimeException) {                    throw (RuntimeException) creationFailure;                } else {                    throw (Error) creationFailure;                }            }            call = rawCall;            if (call == null) {                try {                    call = rawCall = createRawCall();                } catch (IOException | RuntimeException | Error e) {                    throwIfFatal(e); //  Do not assign a fatal error to creationFailure.                    creationFailure = e;                    throw e;                }            }        }        if (canceled) {            call.cancel();        }        return parseResponse(call.execute());    }
ExecutorCallbackCall把网络请求委派给OKHttpCall,后者主要负责:
  • 把接口注解参数转换为okhttp3.Call原始请求
  • 执行okhttp3.Call接口请求,获取Response结果
  • 把ResponseBody转换为接口返回数据类型并回调

1. ServiceMethod.toCall负责将注解参数转换为okhttp3.Call

/** Builds an HTTP request from method arguments. */  okhttp3.Call toCall(@Nullable Object... args) throws IOException {    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,        contentType, hasBody, isFormEncoded, isMultipart);    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.    ParameterHandler[] handlers = (ParameterHandler[]) parameterHandlers;    int argumentCount = args != null ? args.length : 0;    if (argumentCount != handlers.length) {      throw new IllegalArgumentException("Argument count (" + argumentCount          + ") doesn't match expected count (" + handlers.length + ")");    }    for (int p = 0; p < argumentCount; p++) {      handlers[p].apply(requestBuilder, args[p]);    }    return callFactory.newCall(requestBuilder.build());  }  

2. OkHttpCall.parseResponse负责Response解析及请求结果状态的封装回调。

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

3. ServiceMethod.toResponse负责将ResponseBody转换为接口返回数据类型。

*其内部Converter接口负责把HTTP请求响应结果转换可识别的数据格式。举个栗子:*
  • VoidResponseBodyConverter:不做处理,直接返回RequestBody
  • GsonResponseBodyConverter:将字节流转换为Java对象
  • ToStringConverter:将RequestBody转换为String
/** Builds a method return value from an HTTP response body. */  R toResponse(ResponseBody body) throws IOException {    return responseConverter.convert(body);  }
ExecutorCallbackCall.execute同步请求完之后,直接取出responseConverter转换出来的body即为请求结果。
// Fetch and print a list of the contributors to the library.    List contributors = call.execute().body();

到此,一个Retrofit GET同步请求流程基本分析完了。想要加深理解,Read the fucking source code!

更多相关文章

  1. Android创建Native Binder Service
  2. Android(安卓)利用 APT 技术在编译期生成代码
  3. android开发之Parcelable使用详解
  4. Android网络框架综述(一)OkHttp、NoHttp、Volley
  5. Android中用Kotlin Coroutine(协程)和Retrofit进行网络请求和取
  6. Android(安卓)GWES之窗口管理之基本构架原理
  7. 【Service 1】Android(安卓)Remote Service - AIDL
  8. [置顶] Android(安卓)从硬件到应用:一步一步向上爬 5 -- 在Framew
  9. Android(安卓)内容提供器---创建内容提供器(设计数据存储)

随机推荐

  1. 修改项目android的jar包版本
  2. 程序的组件模式
  3. android面试1
  4. Android客户端应用享用传统Web服务
  5. Android基础介绍及Android执行流程
  6. android handle使用方法
  7. Android系统的版本
  8. 构建Android在Windows上的x86模拟器(下)
  9. Android的10毫秒问题 解读Android系统音
  10. Android(安卓)自定义ListView