【Android】Retrofit2使用入门

介绍

Retrofit是Square公司基于OkHttp开发的一款针对Android的网络请求框架。于其他网络框架不同的是,它更多使用注解的方式提供功能。准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装

快速入门

使用retrofit2大致有以下步骤,分别是

  1. 集成

截止北京时间2019/02/12,最新版本为v2.5.0,官方共提供3种方法用于集成到项目中,下面这些还包含了Gson解析器,这个就看个人洗好咯

   <dependency>
     <groupId>com.squareup.retrofit2</groupId>
     <artifactId>retrofit</artifactId>
     <version>2.5.0</version>
   </dependency>
   <dependency>
     <groupId>com.squareup.retrofit2</groupId>
     <artifactId>converter-gson</artifactId>
     <version>2.5.0</version>
   </dependency>
   implementation 'com.squareup.retrofit2:retrofit:2.5.0'
   implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
  1. 创建相关的请求类

    接下来我们就可以创建向服务器发送请求的相关代码。这里先打个比方,假如我现在需要Get请求http://bing.creepersan.com/api/v1/url来获取相应的日本必应历史图片信息。我们可以这样写

   interface BingUrlRequest{
   	
       // @FormUrlEncoding
       @GET("api/v1/url")
       fun getBingUrl(@Query("count") count:Int=12):Call<BingUrlResponse>
   
   }

其中我们可以看到这上面有三个注解(虽然有一个是注释的),他也对应着Retrofit2的三大注解分类,其总表如下

  @HTTP(method = "GET", path = "api/v1/url", hasBody = true)

还有就是,我们可以发现,Retrofit2把URL分成了2部分,注解传的参数只有URL的路径名。那么剩余的服务器域名或者是服务区地址呢?别急,我们在下面就能看到了。

      @FormUrlEncoded
      @POST("test")
      fun getTest(@Field("key") key:String)
      @Multipart
      @POST("test")
      fun upload(@Part file:MultipartBody.Part, @Part("description") description:RequestBody)

​ 那么,请求网络时代码如下

          val file = File("你的路径")
          val requestBody = RequestBody.create(MediaType.parse("image/png"), file)
          val photo = MultipartBody.Part.createFormData("photos", "1.png", requestBody) // 对应 MultipartBody.Part,指上传的图片文件
          val des = RequestBody.create(null, "描述") // 对应 RequestBody,指简单的键值对
  @Streaming
  @GET("test")
  fun upload():Call<BingUrlResponse>

​ 需要注意的是,在这种情况下我们就不能继续使用上面的方法来解释了。否则会报NetworkOnMainThreadException的异常,原因大家都懂得。因此我们需要把最后的接受数据操作放在一个单独的工作线程中。

    // @Header
    @GET("user")
    fun getUser(@Header("Authorization") authorization:String):Call<User>
    
    // @Headers
    @Headers("Authorization: authorization")
    @GET("user")
    fun getUser():Call<User>

以上的效果是一致的,区别在于使用场景和使用方式。@Header用于添加不固定的请求头,@Headers用于添加固定的请求头。@Header作用于方法的参数;@Headers作用于方法

    @FormUrlEncoded
    @Post("test")
    fun getTest(@Field("ip") fitst:String)

如果是FiledMap则如下

    @FormUrlEncoded
    @Post("test")
    fun getTest(@FieldMap fitst:Map<String,Any>)
    @POST("test")
    fun getTest(@Body ip:IP)

其中IP的定义如下

    class IP{
    	var ip:String = ""
    }

通过此方法发送的请求数据为一个Json字符串。需要注意的是,如果提交的是一个Map,那么作用相当于 @Field

    @GET("{path}/test.php")
    fun getTest(@Path("path") path:String):Call<Test>
    @GET
    fun testUrlAndQuery(@Url url:String):Call<ResponseBody>
  1. 创建相关服务器返回信息类

    然后是创建服务器返回的相关信息类。还是请求上面的Api接口,如果请求正常的话,他的回复应该是这样的。

    那么我们可以根据这个Json写出下面的服务器返回数据格式

   class BingUrlImageItemBean{
       var date:Int = 20000000
       var year:Int = 0
       var month:Int = 0
       var day:Int = 0
       var title:String = ""
       var location:String = ""
       var author:String = ""
       var img_url:String = ""
       var img_url_thumbnail:String = ""
       var img_url_base:String = ""
   }
   
   class BingUrlDataBean{
       var itemCount:Int = 0
       var imgList: ArrayList<BingUrlImageItemBean>? = null
   }
   
   class BingUrlResponse{
       var flag:Int = 0
       var data : BingUrlDataBean? = null
   }

需要注意的是,所创建的变量名必须要和Json返回的键名相对应,而且层级关系也要和Json保持一致。

  1. 创建Retrofit实例

    相关代码如下

           val retrofit = Retrofit.Builder()
                   .baseUrl("http://bing.creepersan.com")
                   .addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
                   //.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava平台
                   .build()
  1. 发送请求并处理返回数据

    发送一个异步请求,代码如下所示

   val request = retrofit.create(BingUrlRequest::class.java)
   val call = request.getBingUrl(3)
   call.enqueue(object : Callback<BingUrlResponse> {
       override fun onFailure(call: Call<BingUrlResponse>, t: Throwable) {
           // 连接失败处理
       }
       override fun onResponse(call: Call<BingUrlResponse>, response: Response<BingUrlResponse>) {
           // 连接成功处理
       }
   })

发送一个同步请求代码如下所示

           val request = retrofit.create(BingUrlRequest::class.java)
           val call = request.getBingUrl(3)
           val response = call.execute()
           // 处理response

参考资料

这是一份很详细的 Retrofit 2.0 使用教程 - Carson_Ho

Android进阶之光 - 刘望舒