Android网络访问之Retrofit使用教程
懒到死的程序员 人气:0一、概念
HttpClient | Android 6中移除(API数量多扩展困难)。 |
HttpURLConnection | 目前官方集成的。 |
OKHttp | Square公司出品,底层通讯的实现。 |
Retrofit | Square公司出品,上层接口的封装,更方便使用面向对象思维进行网络操作。 |
二、使用
Android 9开始默认只允许使用 HTTPS 类型的网络请求,HTTP明文传输因为有安全隐患不再支持。坚持使用的话需要配置:右键res目录→New→Directory→创建一个xml目录,右键xml目录→New→File→创建一个network_config.xml文件,修改内容如下:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config> </network-security-config>
Manifest {
//添加网络访问权限
<uses-permission android:name="android.permission.INTERNET" />
//允许HTTP访问
<application
android:networkSecurityConfig="@xml/network_config"
</application>
}
2.1HttpURLConnection
thread { var connection: HttpURLConnection? = null try { val response = StringBuilder() val url = URL("https://www.baidu.com") connection = url.openConnection() as HttpURLConnection connection.connectTimeout = 8000 connection.readTimeout = 8000 //GET请求 val input = connection.inputStream val reader = BufferedReader(InputStreamReader(input)) reader.useLines { response.append(it) } print(response.toString()) //POST请求 connection.requestMethod = "POST" val output = DataOutputStream(connection.outputStream) output.writeBytes("username=admin&password=123456") } catch (e: Exception) { e.printStackTrace() } finally { connection?.disconnect() } }
2.2OKHttp
2.3Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0' //会连带下载 OkHttp和Okio
implementation 'com.squareup.retrofit2:converter-gson:2.k6.1' //会连带下载 GSON
2.3.1 定义实体类
根据 JSON 内容,编写对应的实体类。
data class Person(var name: String, var age: Int)
2.3.2 定义API接口
根据 API 接口,编写对应的访问文件。命名通常以功能名称开头+Service结尾。
@GET | 从服务器获取数据 |
@POST | 向服务器提交数据 |
@PUT @PATCH | 修改服务器上的数据 |
@DELETE | 删除服务器上的数据 |
interface PersonService { //接口1:https://www.baidu.com/person.json @GET("person.json") //表示发起的是GET请求,传入请求的地址(相对路径,重复根路径在后面配置) fun getPerson(): Call<list<Person>> //返回值必须声明成Retrofit内置的Call类型,通过泛型指定服务器返回的具体数据类型 //接口2:https://www.baidu.com/<page>/person.json @GET("{page}/get_data.json") //使用 {page} 占位 fun getData(@Path("page") page: Int): Call<Data> //使用 @Path("page")注解来声明对应参数 //接口3:https://www.baidu.com/person.json?u=<user>&t=<token> @GET("person.json") fun getData(@Query("u") user: String, @Query("t") token: String): Call<Data> //接口4:https://api.caiyunapp.com/v2/place?query=北京&token={token}&lang=zh_CN @GET("v2/place?token=${GlobalApplication.TOKEN}&lang=zh_CN") //不变的参数固定写在GET里 fun searchPlaces(@Query("query") query: String): Call<PlaceResponse> //接口5:https://www.baidu.com/data/<id> @DELETE("data/{id}") fun deleteData(@Path("id") id: String): Call<ResponseBody> //该泛型表示能接受任意类型切不会进行解析 //接口6:https://www.baidu.com/data/create{"id": 1, "content": "The description for this data."} @POST("data/create") fun createData(@Body data: Data): Call<ResponseBody> //将Data对象中的数据转换成JSON格式的文本,并放到HTTP请求的body部分 //接口7:http://example.com/get_data.json // User-Agent: okhttp //header参数就是键值对 // Cache-Control: max-age=0 //静态声明 @Headers("User-Agent: okhttp", "Cache-Control: max-age=0") @GET("get_data.json") fun getData(): Call<Data> //动态声明 @GET("get_data.json") fun getData(@Header("User-Agent") userAgent: String, @Header("Cache-Control") cacheControl: String): Call<Data> }
2.3.3 构建Retrofit对象
val retrofit = Retrofit.Builder() .baseUrl("https://www.baidu.com/") //配置重复的根路径 .addConverterFactory(GsonConverterFactory.create()) //指定解析数据使用的转换库(这里是Gson) .build()
2.3.4 创建API接口实例并调用访问函数
//创建动态代理对象 val personService = retrofit.create(PersonService::class.java) //调用访问函数 personService.getPerson().enqueue(object : Call<List<person>> { //根据注解中配置的地址进行网络请求 override fun onResponse(call: Call<List<person>>, response: Response<List<person>>) { val list = response.body() //得到解析后的对象 } override fun onFailure(call: Call<List<person>>, t: Trouble) { t.printStackTrace() } })
2.3.5 优化
object GlobalRetrofit { private const val BASE_URL = "www.baidu.com/" val retrofit: Retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() //fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass) inline fun <reified T> create(): T = create(T::class.java) } //使用 val personService = GlobalRetrofit.create<PersonService>()
加载全部内容