Android Retrofit的基本使用

什么是Retrofit

        retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了Okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。
        本质过程:App应用程序通过Retrofit请求网络,实质上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由okhttp来完成后续的请求工作。在服务端返回数据后,okhttp将原始数据交给Retrofit,Retrofit根据用户需求解析。

使用介绍

        使用 Retrofit 的步骤共有7个:

        步骤1:添加Retrofit库的依赖
        步骤2:创建 接收服务器返回数据 的类
        步骤3:创建 用于描述网络请求 的接口
        步骤4:创建 Retrofit 实例

        封装了 数据转换、线程切换的操作

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

1.添加依赖

dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    
    implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
   
    

        由于Retrofit是基于OkHttp开发的,因此添加上述第一条依赖会自动将Retrofit、OkHttp和 Okio这几个库一起下载,我们无须再手动引入OkHttp库。

        另外,Retrofit还会将服务器返回的 JSON数据自动解析成对象,因此上述第二条依赖就是一个Retrofit的转换库,它是借助GSON来解析JSON数据的,所以会自动将GSON库一起下载下来,这样我们也不用手动引入GSON库了。除了GSON之外,Retrofit还支持各种其他主流的JSON解析库,包括Jackson、Moshi等,不过毫无疑问GSON是最常用的。

2.创建接收服务器返回数据的类

class App(val id: String, val name: String, val version: String)

3.创建用于描述网络请求的接口

interface AppService {

    @GET("get_data.json")
    fun getAppData():Call<List<App>>

}

        上述代码中有两点需要我们注意。第一就是在getAppData()方法上面添加的注解,这里使用了一个@GET注解,表示当调用getAppData()方法时Retrofit会发起一条GET请求,请求的地址就是我们在@GET注解中传入的具体参数。注意,这里只需要传入请求地址的相对路径即可,根路径我们会在稍后设置。
        第二就是getAppData()方法的返回值必须声明成Retrofit中内置的Call类型,并通过泛型来指定服务器响应的数据应该转换成什么对象。由于服务器响应的是一个包含App数据的JSON数组,因此这里我们将泛型声明成List<App>。当然,Retrofit还提供了强大的Call Adapters功能来允许我们自定义方法返回值的类型,比如Retrofit结合Rxjava使用就可以将返回值声明成 Observable、Flowable等类型,不过这些内容就不在本节的讨论范围内了。

4.使用Retrofit

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main) 
        getAppDataBtn.setOnClickListener {
            val retrofit = Retrofit.Builder()
            .baseUrl("http://10.0.2.2/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        val appService = retrofit.create(AppService::class.java)

        appService.getAppData().enqueue(object : Callback<List<App>> {
        
            override fun onResponse(call: Call<List<App>>,
                   response: Response<List<App>>) { 
                    val list = response.body( ) 
                    if (list != null) {
                        for (app in list) {
                            Log.d("MainActivity", "id is ${app.id}")
                            Log.d("MainActivity", "name is ${app.name}")
                            Log.d("MainActivity", "version is ${app.version}")
                        }
                    }
       	    }	
            override fun onFailure(call: Call<List<App>>,t: Throwable){
                t.printStackTrace()
            }
        })
    }
}
}

        可以看到,在“Get App Data”按钮的点击事件当中,首先使用了Retrofit.Builder来构建一个Retrofit对象,其中baseUrl()方法用于指定所有Retrofit请求的根路径,
addConverterFactory()方法用于指定Retrofit在解析数据时所使用的转换库,这里指定成 GsonConverterFactory。注意这两个方法都是必须调用的。
        有了Retrofit对象之后,我们就可以调用它的create()方法,并传入具体Service接口所对应的Class类型,创建一个该接口的动态代理对象。如果你并不熟悉什么是动态代理也没有关系,你只需要知道有了动态代理对象之后,我们就可以随意调用接口中定义的所有方法,而 Retrofit会自动执行具体的处理就可以了。

        使用时别忘了申请网络权限哦,

    <!-- 访问网络的权限 -->
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

        使用时可能会遇到以下问题:

CLEARTEXT communication to mock-api.com not permitted by network security policy

        这是因为Android P不允许明文访问,而前面的mock地址是http开头的,解决办法是在AndroidManifest中的application内加入下面这段代码即可:

    android:usesCleartextTraffic="true"

        以上就是Retrofit最基本的一次网络请求,但是显然,服务器不可能一直给我们提供静态类型接口,很多情况下,接口中的部分内容很可能会动态变化。接下来我们详细看下Retrofit网络请求接口中主要有哪些注解的使用。

Get请求

假设baseUrl为:http://mock-api.com/2vKVbXK8.mock/

@Query

访问地址

    http://mock-api.com/2vKVbXK8.mock/api/getUserInfo?id=1234
    //1234为传来的参数
    @GET("api/getUserInfo")
    fun getUserInfo(@Query("id") userId : String):Call<App>
    复制代码

   

        如果我们要访问的地址为:baseUrl+getUserInfo?id=1234,以?形式拼接一个参数这种格式时,就使用@Query注解,该注解就是在getUserInfo后面添加?,并且以id=传来的参数userId的形式拼接url

@QueryMap

访问地址

    http://mock-api.com/2vKVbXK8.mock/api/getArticalInfo?id=405&page=1

实例

    @GET("api/getArticalInfo")
    fun getUserInfo(@QueryMap  params : Map<String, String>) : Call<App>

 当要访问的地址是通过?形式拼接多个参数时就使用@QueryMap注解

@Path

访问地址

    http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/1/data
    http://mock-api.com/2vKVbXK8.mock/api/getDynamicInfo/2/data

实例

    @GET("api/getDynamicInfo/{param}/data")
    fun getDynamicInfo(@Path("param") param : int) : Call<App>

        当要访问的地址由某个参数动态拼接而成时,使用@Path注解,上面实例中param这里具体填入的内容是后面调用该方法时传入的参数 

@URl

    @GET
    fun getDynamicUrl(@Url url : String) : Call<ResponseBody> 

当要访问的地址不只是动态的变几个参数,而是整个地址都要变化,甚至是基类地址也要变化时,这种动态地址就要用到@Url注解

@Body

        可以看到@FieldMap注解适合多个相同类型参数的传递,如果多个不同类型传递的话,总不能写多个@Field

Call<ResponseBody> postFieldFun(@Field("key") String key,@Field("num")int num);

        如果要更多种类型的话那就更繁琐了,所以这里我们可以用@Body注解,直接传入一个对象过去,对象内可包含多种类型数据。

    @POST("api/bodyParam")
    fun postBodyFun(@Body postBodyBean : PostBodyBean) :Call<ResponseBody>
   

本文参考自郭霖《Android第一行代码》第三版

参考博客:【精选】android_框架_Retrofit使用详解_retrofit map_写bug的蚊子的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值