阅读 1683

七日打卡——Android之Retrofit2学习

前言

连更几天的数据结构与算法,有点肝不动了,虽然今天刚刚看了红黑树创建操作的具体情况,但是今天还是想给大家介绍一个比较火热的安卓网络请求库Retrofit2,主要还是说一下这一请求库的应用。

一、模拟请求网站

android有着诸多的网络请求架构与网络请求库,在介绍我们今天的主角Retrofit2之前,先介绍一个我们用于测试用的模拟请求网站:mock-api.com/app.html,它可… 建立过程主要分为四个步骤:

  1. 创建自己的模拟系统,并进入模拟系统
  • 创建中:

新建模拟系统

  • 创建完成:

模拟系统给

  1. 进入系统,定义所想要的请求规则(一般都是GET/POST)

左侧需要定义Request请求,右侧需要定义Response响应。当然注意格式一般都是json格式(Request部分也可以选择其他格式,但是表现在url上都大同小异)。 Request请求格式 同时需要注意下大小写之分,因为这对我们后续Retrofit2的使用十分重要。

  • GET请求:

GET

  • POST请求:

POST

二、Retrofit2简介

Retrofit2是Square公司开源的网络请求封装库,其底层是基于OKHttp网络请求框架的实现的,当然OKHttp也是Square公司推出的罢了。搭配其他的框架(GSON格式的Response),Retrofit2使得请求变得简便,搭建变得更容易实现。

三、Retrofit2注解

下面列三个表格进行常用Retrofit2注解说明。一类是请求格式列表,一类是标记,还有一类是网络请求参数

请求格式列表:

注解请求形式说明
@GETget请求
@POSTpost请求
@HEADhead请求
@PUTput请求
@DELETEdelete请求
@PATCHpatch请求,对put请求进行
@OPTIONoption请求
@HTTPhttp/https请求,需要指明三个属性method,path,hasBody

一般最常见的就是使用@GET和@POST注解。 而在GET请求,我们知晓,添加的参数(Query_String)均直接显示在url中。

标记

标记一般都是Post请求的其他几种数据传方式。

参数形式说明
@FormUrlEncodedPost请求上传表单数据
@MultipartPost请求上传文件数据
@StreamingPost请求返回数据流形式数据,适用于大数据场景

网络请求参数列表:

  1. @GET
网络请求参数形式说明
@Query指定url后接单一参数
@QueryMap指定url后接多个参数
  1. @POST
网络请求参数形式说明
@Body用于post请求传输json格式数据
@Field、@FieldMap与@FormUrlEncoded标记合用,用于post请求传输表单数据使用
@Part、@PartMap与@Multipart标记合用,用于post传输文件使用
  1. 通用
网络请求参数形式说明
@Header、@Headers添加请求头(header为添加不固定值的header)
@Path路径替换参数
@URL设置URL

四、Retrofit2使用

在分别给出上述网络请求方式的规则(GET and POST为例)之前,我们先来理清一下发起请求之前所需要做的准备工作。

Step 1 添加依赖库

//build.gradle.kt
dependencies {
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    testImplementation(kotlin("test-junit"))
}
复制代码

这里添加了一个converter-gson用于将response的body进行数据格式转换。

Step 2 开始准备retrofit——定义接口,在其中声明请求函数以及返回 回调

interface WebService {
    @GET("api/webInfo")
    fun getWebInfo(): Call<WebInfo>

    @GET("api/userInfo")
    fun getUserInfo(@Query("id") id :Int): Call<UserInfo>

    @GET("api/article/{bookName}/page/{page}")
    fun getContentOfBook(@Path("bookName") bookName:String, @Path("page") page:Int) :Call<ResponseBody>

    @POST("api/login")
    fun login(@Body account : AccountInfo) : Call<UserInfo>
}
复制代码

我们需要声明一个接口,此处为WebService,用于存储各种需要发送请求,对应于我们模拟网址的请求规则。

GET

ET书籍

    @GET("api/userInfo")
    fun getUserInfo(@Query("id") id :Int): Call<UserInfo>

    @GET("api/article/{bookName}/page/{page}")
    fun getContentOfBook(@Path("bookName") bookName:String, @Path("page") page:Int) :Call<ResponseBody>
复制代码

从如上代码其实很好理解@Query和@Path @Query:/api/userInfo?id=1 @Path:/api/article/zgmtqsx/page/1

POST

登陆

    @POST("api/login")
    fun login(@Body account : AccountInfo) : Call<UserInfo>
复制代码

post请求与上文所说Response字段需要与Call中返回类保持一致,post请求中Body->AsccountInfo也需要与Request请求的json字段保持一致。

Step 3 根据Response响应在定义的接口中定义返回的数据类型

如上面接口Call中的各种类,这些类中的变量定义与Response中的响应一致。

class AccountInfo {
    private var user:String?=null
    private var password:String?=null

    constructor(user :String, password :String) {
        this.user = user
        this.password = password
    }
}
复制代码
class UserInfo {
    private var userName :String?= null
    private var id :Int?= null
    private var account:String?=null
    private var sex :String?= null
    private var age :Int?= null
    private var verifyCode :String?= null

    fun getUserInfo(): String {
        return "\t userName : $userName\n \t id : $id \n \t sex : $sex \n \t age : $age \n \t verifyCode : $verifyCode \n"
    }


    fun getLoginAccountInfo() :String {
        return "\t userName : $userName\n \t id : $id \n \t account : $account \n \t verifyCode : $verifyCode \n"
    }
}
复制代码

正如博主所提醒,类的字段名需要与Response中的字段名保持一致,否则,会发现在Response之外的字段值在返回后为空。

Step 4 实例化Retrofit2,获取网络

    val baseUrl = "http://mock-api.com/mnEPkRgJ.mock/"
    val retrofit :Retrofit = Retrofit.Builder().
    			     baseUrl(baseUrl).
                             addConverterFactory(GsonConverterFactory.create()).build()
    val service :WebService = retrofit.create(WebService::class.java)
复制代码

baseUrl代表着我们的请求前最基础的url,而后get/post请求均是在该url基础上加上参数或者是提交数据。

Step 5 开始网络请求(异步/同步)

Retrofit2 的底层网络请求还是OKHttp的,因此也沿用着同步execute和异步enqueue函数。

同步:execute()

  var repsponse = service.getWebInfo().execute()
    println(repsponse.body())
复制代码

异步:enqueue()

 service.getWebInfo().enqueue(object :Callback<WebInfo>{
        override fun onResponse(call: Call<WebInfo>, response: Response<WebInfo>) {
            if (response != null && response.body() != null) {
                webInfo = response.body()
//                println(response.body())
                println(webInfo.toString())
            }
        }

        override fun onFailure(call: Call<WebInfo>, t: Throwable) {
            println(t.toString())
        }
    })

    service.getUserInfo(id = 1).enqueue(object : Callback<UserInfo>{
        override fun onResponse(call: Call<UserInfo>, response: Response<UserInfo>) {
            lin = response.body()
            println(lin?.getUserInfo())
        }

        override fun onFailure(call: Call<UserInfo>, t: Throwable) {
            println(t.toString())
        }
    })

    service.getContentOfBook("zgmtqsx",1).enqueue(object :Callback<ResponseBody>{
        override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
            println(response)
        }

        override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
            println(t.toString())
        }
    })


    var accountInfo :AccountInfo= AccountInfo("44244242","12345")

    service.login(accountInfo).enqueue(object :Callback<UserInfo>{
        override fun onResponse(call: Call<UserInfo>, response: Response<UserInfo>) {
            if (response.isSuccessful) {
                lin = response.body()
                println(lin?.getLoginAccountInfo())
            }
        }

        override fun onFailure(call: Call<UserInfo>, t: Throwable) {
            println(t.toString())
        }
    })
复制代码

五、总结

以上就是博主目前所了解到REtrofit2的使用,当然文中并没有举例出全部的所有的例子,但是也是相对常见且相对够用的操作。希望对大家学习Retrofit2有所帮助。

文章分类
Android
文章标签