`
xixinfei
  • 浏览: 414168 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android Retrofit的使用

阅读更多

原文   http://blog.fangjie.info/2016/07/14/我对Retrofit的认识/

 

Retrofit的想的文章很多,先罗列下 我在看过觉得不错的几篇文章:

 

这两篇文章都是stay写的,觉得真心赞。当然我也不重复他文章里面的内容了,读者们完全可以直接看他的文章。当然我写这篇文章,主要想自我总结下,谈谈自己的认识而已。

首先Retrofit之所以这么火。我觉得他里面设计模式用的好,特别是适配器模式那里。总体来说,我觉得Retrofit精髓就在三点。1、动 态代理,用注解来生成请求参数;2、适配器模式的应用,请求返回各种CallAdapter,可扩展到RxJava、Java8,还有任何你自己写的 Adapter;3、Converter,你可以把请求的响应用各种Converter转成你的需求上。>

接下来细细说这些东西。

Retrofit一个简单的使用过程是这样的:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(API_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build();

// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);

// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");

call.enqueue(new Callback<List<Contributor>>() {
  @Override
  public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {

  }

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

  }
});

上面过程可以看成四步,也是接下来要分析的四个步骤。
1、Retrofit.Builder().build()
2、retrofit.create
3、 github.contributors
4、call.enqueue

第一步、Retrofit.Builder().build()

就是用到建造者模式。

   public Retrofit build() {
     if (baseUrl == null) {
       throw new IllegalStateException("Base URL required.");
     }
// 忽略不看 这个工厂模式基本没什么作用了,目前来说Retrofit只支持OkHttp,不能支持URLConnection或者HTTPClient
     okhttp3.Call.Factory callFactory = this.callFactory;
     if (callFactory == null) {
     //这里首先创建了一个OkHttpClient对象
       callFactory = new OkHttpClient();
     }

//然后创建Executor对象
     Executor callbackExecutor = this.callbackExecutor;
     if (callbackExecutor == null) {
       callbackExecutor = platform.defaultCallbackExecutor();
     }

//然后创建 CallAdapter对象
     // 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));
// 创建Converter对象
     // Make a defensive copy of the converters.
     List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

总结这步的步骤就是准备好要用到的东西,callAdapter是请求返回的对象,Converter是转换器,转换请求的响应到对应的实体对象,OkHttpClient是具体的OkHttp的请求客户端。

第二步、Retrofit.create();

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

这里就是动态代理的原理,在使用Retrofit的时候,我们会把网络请求的接口写成这样一个接口方法。第二步只是准备这样一个代理。

第三步、调用这个接口方法

调用的时候才会真正的触发这样一个过程。

public interface GitHub {
  @GET("/repos/{owner}/{repo}/contributors")
  Call<List<Contributor>> contributors(
      @Path("owner") String owner,
      @Path("repo") String repo);
}

动态代理就是拦截GitHub接口方法调用,但接下来主要做两个工作:1、拿到这个方法的各种注解,然后配置OkHttp的网络请求参数。2、把真实的网络请求的OkHttpCall转换成该接口对应的CallAdapter。

3.1、loadServiceMethod()

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

这里面对每个接口方法的注解解析生成ServiceMethod对象,使用了一个缓存,避免一个网络请求在多次调用的时候频繁的解析注解,毕竟注解解析过程消耗比较大。

这里面主要的工作又在ServiceMethod.Builder().build();

   public ServiceMethod build() {

     callAdapter = createCallAdapter();
//... 
     responseConverter = createResponseConverter();

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

这里简单来说就是做三件事,1、找到对应的CallAdapter,2、找到对应的Converter,3、解析注解生成参数

3.1.1 找到对应的CallAdapter

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

在找对应的callAdapter的时候,是根据不同的CallAdapterFactory的返回类型来区分的,比如我们看下默认的ExecutorCallAdapterFactory

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

这里就是说 返回类型是Call.class,都是使用 ExecutorCallAdapterFactory创建的的ExecutorCallbackCall。

而RxJava对应的返回类型就是Observable.class。

3.1.2 找对应的Converter

 public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
     Type type, Annotation[] annotations) {

   int start = converterFactories.indexOf(skipPast) + 1;
   for (int i = start, count = converterFactories.size(); i < count; i++) {
     Converter<ResponseBody, ?> converter =
         converterFactories.get(i).responseBodyConverter(type, annotations, this);
     if (converter != null) {
       //noinspection unchecked
       return (Converter<ResponseBody, T>) converter;
     }
   }
}

看下GsonConverterFactory,

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

3.1.3 parseMethodAnnotation

最后就是解析请求参数的工作,这部分就是解析注解上配置的网络请求参数。很多,很琐碎。

三步完成之后,ServiceMethod对象就build出来了,然后放到缓存中,避免下次再build。再回到主线的第三步,loadServiceMethod完成之后,就是创建一个OkHttpCall。

3.2、创建OKhttpCall 并adapter对应的call

这个OkHttpCall才是真正OkHttp请求的回调,但是针对我们使用的不同的回调,比如:RxJava的Observable、 Call,所以有一层转换的关系,把OkHttpCall转成对应的Observable和Call。就是 serviceMethod.callAdapter.adapt(okHttpCall)的工作。

就拿默认的CallAdapter说吧,这里是个匿名类。

return new CallAdapter<Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

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

他的实现就是创建的一个ExecutorCallbackCall作为Call返回了。当然它里面还也持有OkHttpCall的引用。目的是为了上层的回调,下面会讲。

好了至此,主线的第三步完成,一切准备就绪了,就等网络请求了。网络请求分为异步、同步的,这里只讲异步的。同步的更简单。

第四步、call.enqueue

这个Call是对应选择的call,这里讲ExecutorCallbackCall

红色框起来的是,adapte步骤转换的时候,对应的call持有的真正网络请求OkHttp的Call。而这里的callbackExecutor又是运行在主线程的(这里没有跟踪代码,可以自己去查下,是这样的),所以callback的回调就运行在主线程了。

最后补充第五步,从主线上来看是看不出来Converter发挥作用的地方。

第五步、Converter的转换

就在第四步请求的时候,真实的网络请求OkHttpCall在enque的时候,里面有个onResponse,这里面调用了一个parseResponse,

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();




  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.toResponse,这里毫无疑问的就是找到把之前找出的Converter拿出来,进行convert操作。

T toResponse(ResponseBody body) throws IOException {
  return responseConverter.convert(body);
}

至此一个完整的Retrofit的网络请求就已经完成了!

当然这里只讲了一个CallbackFactory,一个Conveter,Retrofit火就在于它能够扩张各种CallbackFactory,各种Conveter。当然配合 RxJavaCallbackFactory也是它火的一个原因。

自己拿源码走一遍吧!理解会更深刻!!

分享到:
评论

相关推荐

    Android Retrofit的简单使用

    **Android Retrofit 简单使用** Retrofit 是一个在 Android 和 Java 平台上广泛使用的网络请求库,它是由 Square 公司开发的。Retrofit 的核心理念是将 HTTP API 转换为 Java 接口,使网络请求变得更加简洁、易用。...

    Android Retrofit2使用Demo

    **Android Retrofit2使用Demo** Retrofit2是Google推出的一个强大的网络请求库,它极大地简化了Android应用中的网络通信。Retrofit2基于OkHttp,提供了一种类型安全的HTTP客户端,使得开发者可以方便地进行RESTful ...

    android retrofit上传与下载文件

    总结一下,Android中使用Retrofit进行文件上传与下载的关键步骤包括: 1. 定义Retrofit服务接口,使用`@Multipart`、`@POST`、`@GET`、`@Part`和`@Query`等注解。 2. 创建`RequestBody`实例,封装文件数据。 3. 调用...

    Android实战——Retrofit2的使用和封装

    Android实战——Retrofit2的使用和封装

    Android-Retrofit2文件上传及其进度显示

    在Android中,通常会使用`subscribeOn(Schedulers.io())`来调度上传任务到后台线程,`observeOn(AndroidSchedulers.mainThread())`则确保更新UI操作在主线程进行: ```java apiService.uploadFile(part, ...

    Android retrofit+rxjava+okhttp 学习案例

    在Android开发中,Retrofit、RxJava和OkHttp是三个非常重要的库,它们共同构建了高效、简洁的网络请求框架。下面将详细讲解这三个库及其结合使用的知识点。 **Retrofit** 是一个由Square公司开发的Android和Java...

    Android Retrofit + RxJava使用详解

    博客地址:http://blog.csdn.net/kong_gu_you_lan/article/details/73504345 GitHub地址:https://github.com/alidili/Demos/tree/master/RetrofitDemo

    AndroidRetrofit.zip

    总之,"AndroidRetrofit.zip"项目为你提供了一个使用ohttp、Retrofit和RxJava进行网络调用和文件下载的实例,对于学习和理解这些库的结合使用具有很高的参考价值。你可以通过阅读代码、运行示例,深入理解这些技术在...

    Android中Retrofit2.0的使用Demo

    总的来说,这个Demo展示了如何在Android项目中使用Retrofit2.0进行网络请求,以及结合Gson进行数据解析。通过这种方式,开发者可以更专注于业务逻辑,而不是网络通信的底层实现。这个实践有助于提高代码的可读性和可...

    Android-以最简洁的Api让Retrofit同时支持多个BaseUrl以及动态改变BaseUrl

    总的来说,通过使用RetrofitUrlManager,开发者可以轻松地在Android应用中实现Retrofit对多个BaseUrl的支持和动态切换,使得网络请求的管理更加灵活。这个库不仅简化了代码,也提高了应用的适应性和可靠性。在实际...

    Retrofit2 使用Demo示例

    Retrofit2 使用Demo

    Android-retrofit简单封装实现公共参数get和post统一处理

    在Android开发中,网络编程是不可或缺的一部分,而Retrofit库因其简洁、强大的特性,成为许多开发者首选的HTTP客户端工具。本篇文章将详细讲解如何对Retrofit进行简单的封装,以实现公共参数在GET和POST请求中的统一...

    Android开发-Retrofit-AndroidStudio(四)simplexml解析XML_免积分

    在本教程中,我们将深入探讨如何在Android Studio项目中使用Retrofit与simplexml库一起解析XML数据。简单XML库(Simple XML)是Java中一个轻量级、高效的XML序列化和反序列化库,非常适合处理XML格式的数据。 首先...

    【Android】RxJava2+Retrofit2+OkHttp3的基础、封装和项目中的使用

    在Android中,RxJava可以与Retrofit结合使用,通过Observables处理网络请求的结果,支持链式调用,使得代码更加简洁和易读。 OkHttp3是一个高效的HTTP客户端,它提供了比Android自带的HttpURLConnection更优秀的...

    Android开发之Retrofit+RxJava的使用

    在Android应用开发中,Retrofit和RxJava是两个非常重要的库,它们可以帮助开发者构建优雅、简洁的网络请求和异步处理逻辑。Retrofit是由Square公司开发的一款类型安全的HTTP客户端,而RxJava则是一个响应式编程库,...

    Android 基于 Retrofit2+Okhttp3 通过SOAP协议请求WebService.zip

    要在Android应用中使用Retrofit2和OkHttp3进行SOAP请求,我们需要以下步骤: 1. 添加依赖:首先在项目的build.gradle文件中添加Retrofit2和OkHttp3的依赖项。 ```groovy dependencies { implementation '...

    retrofit下载apk文件

    retrofit下载apk文件,retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit...

    MVP+Retrofit+RxAndroid使用

    在Android开发中,MVP(Model-View-Presenter)架构模式、Retrofit网络库和RxAndroid库是常见的组合,它们可以有效地提升应用的可维护性和性能。本篇将详细讲解这三个技术的使用方法及其结合应用。 **MVP架构模式**...

    Android Retrofit框架解析

    **Android Retrofit框架解析** 在Android应用开发中,网络请求是必不可少的部分,而Retrofit作为一款优秀的网络请求库,因其简洁的API设计和强大的功能,深受开发者喜爱。Retrofit由Square公司开发,它允许我们将...

    Android-retrofit2极简封装极简接入

    在Android开发中,网络编程是不可或缺的一部分,而Retrofit2是一个非常流行的网络请求库,它提供了优雅的API设计,使得网络请求变得简单易懂。本文将深入探讨如何对Retrofit2进行极简封装以及如何实现极简接入,帮助...

Global site tag (gtag.js) - Google Analytics