Retrofit使用入门

QuibblerQuibbler 2021-03-23 约 12 分钟 1786 次阅读

Retrofit使用入门

每当深入学习一个优秀的开源框架前,先了解它是干什么,怎么用。从最基本的使用开始,不断探索深处的实现原理。用OkHttp作了铺垫,顺理成章的该学一下移动开发中另一个热门框架:Retrofit。 

1、Retrofit简介

Retrofit和OkHttp都出自大名鼎鼎的Square公司。算是亲兄弟了,OkHttp是哥哥,Retrofit是弟弟。关于OkHttp前段时间已经从头到尾看了一遍,从OkHttp的基本用法开始。

1.1、介绍

Retrofit是基于OkHttp封装的网络请求框架:网络请求由OkHttp完成,而Retrofit负责网络请求接口的封装。

GitHub:square/retrofit

Guide:Retrofit A type-safe HTTP client for Android and Java

1.2、引入依赖

强大的开源库往往只需要最简单的添加方式,就可以在项目中使用。开源库的版本查询详见Maven仓库搜索开源库。

//Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

除了Retrofit本体,还有附带的很多转换器Converter可以添加到项目直接使用(对应的版本去MavenCenter查):

//Gson
    implementation 'com.squareup.retrofit2:converter-gson'
    //Jackson
    implementation 'com.squareup.retrofit2:converter-jackson'
    //Moshi
    implementation 'com.squareup.retrofit2:converter-moshi'
    //Protobuf
    implementation 'com.squareup.retrofit2:converter-protobuf'
    //Wire
    implementation 'com.squareup.retrofit2:converter-wire'
    //Simple Framework
    implementation 'com.squareup.retrofit2:converter-simplexml'
    //Scalars
    implementation 'com.squareup.retrofit2:converter-scalars'

当然也可以自定义Retrofit的Converter转换器,随着Retrofit的不断深入了解,咱再解锁Retrofit的全部用法。

2、Retrofit快速入门

先从简单的上手,使用Retrofit实现最基本的GET网络请求。API使用本服务器搭建的:http://quibbler.cn:3000/。

2.1、创建Retrofit实例

和创建OkHttpClient有点类似,都采用建造者模式。通过内部Retrofit.Builder类创建定制的Retrofit实例:

val retrofit = Retrofit.Builder()
            .baseUrl("http://quibbler.cn:3000/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

服务端API根地址baseUrl必须非空,baseUrl在最后一步build()方法中校验,如果为空则构造Retrofit实例的时候抛出异常:

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

所以在构造Retrofit实例的时候必须调用baseUrl()方法设置Retrofit的baseUrl。注意,还有一点,baseUrl必须要以 "/" 结尾,否则又会抛出异常。这就是阅读源码的重要性,不仅要知道异常会发生,还要知道为什么、从哪里抛出异常。

/**
     * Set the API base URL.
     *
     * <p>The specified endpoint values (such as with {@link GET @GET}) are resolved against this
     * value using {@link HttpUrl#resolve(String)}. The behavior of this matches that of an {@code
     * <a href="">} link on a website resolving on the current URL.
     * ... ...
     * <p>Base URL: http://example.com/<br>
     * Endpoint: https://github.com/square/retrofit/<br>
     * Result: https://github.com/square/retrofit/
     */
    public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      //强制要求必须以 / 斜杠结尾
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

2.2、注解抽象API接口

Retrofit的核心之一就是注解,通过注解将网络请求抽象为接口。Retrofit框架共定义了25个注解,分别负责不同的功能。这里只是先简单演示一下,条条大路通罗马,至于其它注解以后再逐个了解它们的具体作用。

用HTTP网络请求最常用的GET方法对应的注解@GET定义一个接口:

interface SearchService {
     @GET("search")
     fun getSearchResult(@Query("keywords") keyword: String): Call<SearchBean>
  }

API请求接口必须定义为interface,通过Retrofit实例的create()方法创建接口实例的时候会校验是否是interface,若不是则抛出异常。

public <T> T create(final Class<T> service) {
     validateServiceInterface(service);
     ...
  }
  
  private void validateServiceInterface(Class<?> service) {
     if (!service.isInterface()) {
        throw new IllegalArgumentException("API declarations must be interfaces.");
     }
    ...
  }

用注解定义好网络请求接口,就可以用2.1节定制好的Retrofit实例的create(final Class<T> service)方法获取接口实例。源码比较复杂 (涉及到反射、代理、各种设计模式等) 以后深入理解。

val searchService: SearchService = retrofit.create(SearchService::class.java)

2.3、创建Call异步请求网络

服务端返回的数据是Json格式,所以我们将返回结果定义成对应的Bean类:SearchResult。推荐一个工具,可以一键生成Json对应的Bean:一键生成实体类插件:GsonFormatPlus。Retrofit请求网络后会使用Gson转换器GsonConverterFactory将响应直接解析成对应的SearchResult对象。

使用2.2节中获取到的API接口实例,调用接口中定义的方法获取Call<T>。此Call非OkHttp中的Call,随着源码的深入研究一切都会揭开。

val call: Call<SearchBean> = searchService.getSearchResult("周杰伦")

获取到Retrofit框架中的Call<T>就可以发起网络请求,可以使用execute()同步请求,或者保留异步请求enqueue()。

call.enqueue(object : Callback<SearchBean> {
        override fun onResponse(call: Call<SearchBean>, response: Response<SearchBean>) {
            //在UI线程回调
        }
        override fun onFailure(call: Call<SearchBean>, t: Throwable) {
            
        }
    })

注意一点区别:Retrofit的网络响应Callback是在UI线程回调,内部做了切换。而OkHttp默认是在子线程回调。

本篇结尾到这里,已经熟悉并能够使用Retrofit进行网络请求。作为一个开发者,只会调用开源库的API是远远不够的。接下来开始深入摸索Retrofit的注解、请求原理、设计模式及转换器等。

相关推荐

精选
Airbnb开源项目
开源

Airbnb开源项目

Airbnb Engineering & Data ScienceAirflow Use Apache Airflow (incubating) to author workflows as directed acyclic graphs (DAGs) of tasks12,263Airpal Web UI for PrestoDB2,502Aerosolve A machine learning

1.8k
OkHttp线程池和连接池
开源

OkHttp线程池和连接池

OkHttp线程池和连接池了解了OkHttp的网络请求流程以及拦截器实现原理,再关注OkHttp中两个重要的:OkHttp的线程池和连接池。1、OkHttp线程池在OkHttp网络请求流程一文中,我们分析了OkHttp异步和同步请求流程。请求最后都在Dispatcher中分发调度处理,最后被ExecutorService执行。1.1、DispatcherDispatcher中执行任务的执行器是ex

5.2k
优美的开源动效库:Lottie
开源

优美的开源动效库:Lottie

优美的开源动效库:Lottie1、强大的动效LottieLottie是一个适用于Android,iOS,Web和Windows的库,它可以使用Bodymovin解析以json格式导出的Adobe After Effects动画,并在移动设备和Web上原生渲染它们!GitHub:https://github.com/airbnb/lottie-androidLottie官网:http://airbn

4.3k