Retrofit的使用

Retrofit的使用

标题

前言
在Andrroid开发中,网络请求十分常用
而在Android网络请求库中,Retrofit是当下最热的一个网络请求库

1.简介

介绍:一个RESTful的HTTP网络请求框架(基于OkHTTP)
作者:Square

功能:

  • 基于OKHTTP&遵循RestfulAPI的设计风格
  • 通过注解配置网络请求参数
  • 支持同步&异步网络请求
  • 支持多种数据的解析&序列化格式(Gson,Json,XML,Protobuf)
  • 提供对RxJava支持

优点

  • 功能强大:支持同步异步,支持多种数据的解析&序列化格式、支持RxJava
  • 简介易用:通过注解配置网络请求参数、采用大量的设计模式简化使用
  • 可拓展性好:功能模块高度封装、解耦彻底,如自定义Converters等
  • 应用场景:任何网络请求的需求场景都可以使用(特别是后台API遵循RestfuAPI设计风格&项目中使用到RxJava)

需要注意的是:

准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。

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

2.使用步骤

步骤一:导入Retrofit库的依赖
步骤二:开启INTERENT权限
步骤三:创建用于接收服务器返回数据的Data类
步骤四:创建用于描述网络请求的接口
步骤五:创建Retrofit实例
步骤六:创建网络请求的接口实例
步骤七:配置网络请求参数并发送网络请求(同步/异步)
步骤八:处理服务器返回的数据

接下来通过一个示例来一步步进行详解:

注意:该示例就是使用Retrofit访问ip-api.com,查询指定的IP地址,并将查询到的该地址所属的国家省、市、运营商等信息记录到日志中。

步骤一

:导入Retrofit库的依赖
build.gradle:
//retrofit核心包文件
implementation group: 'com.squareup.retrofit2', name: 'retrofit', version: '2.9.0'
//Retrofit转换库,借助GSON来解析JSON数据的
implementation group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.9.0'

步骤二:开启INTERENT权限

AndroidManifest.xml:
<!--申请INTERNET权限
    Android应用访问网络时需要先设置权限,在AndroidManifest.xml文件里设置权限:
 -->
    <uses-permission android:name="android.permission.INTERNET" />

步骤三:创建用于接收服务器返回数据的Data类

InfoVo:
//由于Retrofit会借助GSON将JSON数据转换为对象,所以需要创建一个Vo类
data class InfoVo(val `as`: String,
                  val city: String,
                  val country: String,
                  val countryCode: String,
                  val isp: String,
                  val lat: Double,
                  val lon: Double,
                  val org: String,
                  val query: String,
                  val region: String,
                  val regionName: String,
                  val status: String,
                  val timezone: String,
                  val zip: String)

步骤四:创建用于描述网络请求的接口

InfoService:
//接口定义
interface InfoService {
    @GET("json")
    fun getInfo():Call<InfoVo>//服务器接口中的方法用来返回Call对象,可以直接以Vo对象的形式获取网站的响应
    @GET("json/{ip}")
    fun getIpInfo(@Path("ip") ip:String,@Query("lang") lang:String):Call<InfoVo>
    /*
        @Path注解:Path是网址中的参数,例如:trades/{userId}

        @Query注解:表示?后面的参数,例如:trades/{userId}?token={token}
     */
}

下面介绍Retrofit网络请求接口的注解类型:

注解说明

第一类:网络请求方法
详细说明:@GET、@POST、@PUT、@DELETE、@HEAD

以上方法分别对应 HTTP中的网络请求方式
@GET(“json/{ip}”)
fun getIpInfo(@Path(“ip”) ip:String,@Query(“lang”) lang:String):Call
@GET注解的作用:采用Get方法发送网络请求
getIpInfo():接收网络请求数据的方法
其中返回值类型类call<*>,*是接收数据的类(即上面定义的InfoVo类)
这里需要注意的是:
URL的组成:Retrofit把网络请求的URL分成了两部分设置

//第一部分:在网络请求接口的注解设置
@GET("json/{ip}")
    fun getIpInfo(@Path("ip") ip:String,@Query("lang") lang:String):Call<InfoVo>
//第二部分:在床架Retrifit实例时通过.baseUrl设置
//定义常量
    private const val BASE_URL="http://ip-api.com/"

    //创建一个retrofit对象
    private val retrofit=Retrofit.Builder()
        .baseUrl(BASE_URL)//标识所有retrofit请求的跟路径
        .addConverterFactory(GsonConverterFactory.create())//标识retrofit在解析数据时所使用的转换库
        .build()

网络请求的完整URL=在创建Retrofit实例时通过baseUrl()设置+网络请求接口的注解设置
具体的整合规则如下:

一般建议使用第三种方式,并采用同一种路径形式
第二类:标记

标记的具体使用
第三类:网络请求参数

网络请求参数的详细说明

步骤五:创建Retrofit实例

由于构建出来的Retrofit对象是全局通用的,只需要再调用create()方法是针对不同的Service接口传入响应的Class类即可。所以将通用的这部分功能进行了封装,从而简化获取Service接口动态代理的过程。
ServiceCreator:(Kotlin中的单例类)

//创建一个ServiceCreator单例类
object ServiceCreator {
    //定义常量
    private const val BASE_URL="http://ip-api.com/"

    //创建一个retrofit对象
    private val retrofit=Retrofit.Builder()
        .baseUrl(BASE_URL)//标识所有retrofit请求的跟路径
        .addConverterFactory(GsonConverterFactory.create())//标识retrofit在解析数据时所使用的转换库
        .build()

    /**
     * 调用create方法,传入service接口对应的Class类型,创建一个该接口的动态代理对象
     *
     * 动态代理:有了这个动态代理对象后,我们就可以随意调用接口中定义的所有方法
     */
    fun <T> create(serviceClass:Class<T>):T= retrofit.create(serviceClass)

}

需要注意的是:这里使用的是https://ip-api.com/对外提供IP地址查询服务,可以查询IP地址的详细信息。

没有进行封装的实例代码:

//获取服务接口的实例
        val retrofit = Retrofit.Builder()
                //完整url的基础部分,结合服务接口中GET声明的路径就成文了完整的url
            .baseUrl("http://ip-api.com/")
                //向retrofit对象上添加Gson转换器(Gson将json格式的字符串转化为对象)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        val ipService = retrofit.create(IpInfoService::class.java)

关于数据解析器:
Retrofit支持多种数据解析方式
使用时需要在Gradle添加依赖

关于网络请求适配器(CallAdapter):
Retrofit支持多种网络请求适配器方式:guava、Java8和rxjava
使用时如使用的是 Android 默认的 CallAdapter,则不需要添加网络请求适配器的依赖,否则则需要按照需求进行添加
使用时需要在Gradle添加依赖:

Retrofit 提供的 CallAdapter

步骤六:创建网络请求的接口实例

创建网络请求的接口实例

//创建网络请求的接口实例
    val ipInfoService=ServiceCreator.create(InfoService::class.java)

步骤七:配置网络请求参数并发送网络请求(同步/异步)

Retrofit封装了数据转换、线程切换的操作
无请求参数的异步请求:

//ipInfoService.getInfo()方法返回的是Call对象
        //Call对象再调用enqueue方法
        //通过匿名对象表达式继承Callback接口实现其onResponse和onFailure方法
        val appService= ipInfoService.getInfo().enqueue(object :Callback<InfoVo>{
            /**
             *   该方法为回调方法
             *   请求成功后进行回调
             */
            override fun onResponse(call: Call<InfoVo>, response: Response<InfoVo>) {
                //得到解析后的对象
                val item = response.body()
                //判空处理
                if (item != null) {
                    //打印到日志中
                    Log.i("getCountry()", item.country)
                    Log.i("getRegion()", item.region)
                    Log.i("getCity()", item.city)
                    Log.i("getIsp", item.isp)
                }
            }
            /**
             *   该方法为回调方法
             *   请求失败后进行回调
             */
            override fun onFailure(call: Call<InfoVo>, t: Throwable) {
                t.printStackTrace()
            }

含有请求参数的异步请求:

ipInfoService.getIpInfo("8.8.8.8","zh-CN").enqueue(object : Callback<InfoVo> {
            override fun onResponse(call: Call<InfoVo>, response: Response<InfoVo>) {
                val item = response.body()
                if (item != null) {
                    //使用vo对象处理数据
                    Log.i("getCountry()", item.country)
                    Log.i("getRegion()", item.region)
                    Log.i("getCity()", item.city)
                    Log.i("getIsp", item.isp)
                }
            }

            override fun onFailure(call: Call<InfoVo>, t: Throwable) {
                t.printStackTrace()
            }

发送网络同步请求:
Response response = call.execute()

步骤八:处理服务器返回的数据

通过response类的body()对返回的数据进行处理

override fun onResponse(call: Call<InfoVo>, response: Response<InfoVo>) {
				//获取到请求数据
                val item = response.body()
                if (item != null) {
                    //使用vo对象处理数据
                    Log.i("getCountry()", item.country)
                    Log.i("getRegion()", item.region)
                    Log.i("getCity()", item.city)
                    Log.i("getIsp", item.isp)
                }
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值