需要先在项目中添加必要的依赖库。编辑app/build.gradle文件,在dependencies闭包中添加如下内容:
dependencies {
...
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
}
使用举例 1.新增一个实体类App类
data class App(val id: String, val name: String, val version: String)
2.定义一个接口文件,新建AppService接口
interface AppService {
@GET("get_data.json")
fun getAppData(): Call<List<App>>
}
上述代码中有两点需要我们注意。第一就是在getAppData()方法上面添加的注解,这里使用了一个@GET注解,表示当调用getAppData()方法时Retrofit会发起一条GET请求,请求的地址就是我们在@GET注解中传入的具体参数。注意,这里只需要传入请求地址的相对路径即可,根路径我们会在稍后设置。
第二就是getAppData()方法的返回值必须声明成Retrofit中内置的Call类型,并通过泛型来指定服务器响应的数据应该转换成什么对象。由于服务器响应的是一个包含App数据的JSON数组,因此这里我们将泛型声明成List。当然,Retrofit还提供了强大的Call Adapters功能来允许我们自定义方法返回值的类型。
3.在activity_main.xml中定义一个按钮来测试Retrofit网络请求事件,我们在它的点击事件中处理具体的网络请求逻辑即可。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/getAppDataBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Get App Data" />
</LinearLayout>
现在修改MainActivity中的代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getAppDataBtn.setOnClickListener {
val retrofit = Retrofit.Builder().baseUrl("url")
.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()
}
})
}
}
}
4.处理复杂的接口地址类型 首先先定义一个实体类Data
data class Data(val id: String, val content: String)
情况一:接口地址是静态的,永远不会改变。那么对应到Retrofit当中,使用如下的写法即可:
GET http://example.com/get_data.json
interface ExampleService {
@GET("get_data.json")
fun getData(): Call<Data>
}
情况二:在很多场景下,接口地址中的部分内容可能会是动态变化的。当该方法发起请求时,Retrofit就会自动将page参数的值替换到占位符的位置,从而组成一个合法的请求地址。
GET http://example.com/<page>/get_data.json
interface ExampleService {
@GET("{page}/get_data.json")
fun getData(@Path("page") page: Int): Call<Data>
}
情况三:当我们需要传入一系列参数时:这是一种标准的带参数GET请求的格式。接口地址的最后使用问号来连接参数部分,每个参数都是一个使用等号连接的键值对,多个参数之间使用“&”符号进行分隔。
GET http://example.com/get_data.json?u=<user>&t=<token>
interface ExampleService {
@GET("get_data.json")
fun getData(@Query("u") user: String, @Query("t") token: String): Call<Data>
}
这里在getData()方法中添加了user和token这两个参数,并使用@Query注解对它们进行声明。这样当发起网络请求的时候,Retrofit就会自动按照带参数GET请求的格式将这两个参数构建到请求地址当中。
情况四:Retrofit对所有常用的HTTP请求类型都进行了支持,使用@GET、@POST、@PUT、@PATCH、@DELETE注解,就可以让Retrofit发出相应类型的请求了。
DELETE http://example.com/data/<id>
interface ExampleService {
@DELETE("data/{id}")
fun deleteData(@Path("id") id: String): Call<ResponseBody>
}
情况五:如果我们需要向服务器提交数据该怎么写呢?
POST http://example.com/data/create
{"id": 1, "content": "The description for this data."}
interface ExampleService {
@POST("data/create")
fun createData(@Body data: Data): Call<ResponseBody>
}
情况六:有些服务器接口还可能会要求我们在HTTP请求的header中指定参数
GET http://example.com/get_data.json
User-Agent: okhttp
Cache-Control: max-age=0
interface ExampleService {
@Headers("User-Agent: okhttp", "Cache-Control: max-age=0")
@GET("get_data.json")
fun getData(): Call<Data>
}
interface ExampleService {
@GET("get_data.json")
fun getData(@Header("User-Agent") userAgent: String,
@Header("Cache-Control") cacheControl: String): Call<Data>
}
|