目录
Retrofit简介
Retrofit是一款由Square公司开发的网络库,但是它和OkHttp的定位完全不同。
OkHttp侧重的是底层通信的实现,而Retrofit侧重的是上层接口的封装。
事实上,Retrofit就是Square公司在OkHttp的基础上进一步开发出来的应用层网络通信库,使得我们可以用更加面向对象的思维进行网络操作。
Retrofit的项目主页地址是:
https://github.com/square/retrofit
添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
Retrofit基本使用
1.根据Http接口创建kotlin接口
interface HttpbinService {
@GET("get")
fun get(@Query("userName")userName: String,@Query("password") pwd: String):Call<ResponseBody>
@POST("post")
@FormUrlEncoded
fun post(@Field("userName")userName:String, @Field("password")pwd:String):Call<ResponseBody>
}
2.创建Retrofit对象,并生成接口实现类对象。
val retrofit = Retrofit.Builder().baseUrl("https://www.httpbin.org/").build()
val httpbinService: HttpbinService = retrofit.create(HttpbinService::class.java)
3.接口实现类对象调用对应方法获得响应。
val call: retrofit2.Call<ResponseBody> = httpbinService.post("xxx", "xxx")
call.enqueue(object : retrofit2.Callback<ResponseBody> {
//请求完成
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
try {
Log.e("data", "${response.body()?.string()}")
} catch (e: Exception) {
e.printStackTrace()
}
}
//请求失败
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
TODO("Not yet implemented")
}
})
Retrofit的注解
方法注解:@GET,@POST,@PUT,@DELECTE,@PATH,@HEAD,@OPTIONS,@HTTP
标记注解:@FormUrlEncoded,@Multiparty,@Streaming
参数注解:@Query,@QueryMap,@Body,@Field,@FieldMap,@Part,@PartMap
其他注解:@Path,@Header,@Headers,@Url
(1) @GET
https://www.httpbin.org/get
@GET("get")
fun get():Call<ResponseBody>
这里使用了一个@GET注解,表示当调用get()方法时Retrofit会发起一条GET请求,请求的地址就是我们在@GET注解中传入的具体参数。另外,get()方法的返回值必须声明成Retrofit中内置的Call类型,并通过泛型来指定服务器响应的数据应该转换成什么对象。
(2) @GET, @Query
https://www.httpbin.org/get?userName=<userName>&password=<pwd>
@GET("get")
fun get(@Query("userName")userName: String,@Query("password") pwd: String):Call<ResponseBody>
这里在get方法中添加了两个参数userName和pwd,并使用 @Query对他们进行声明,这样当发起网络请求时,Retrofit就会自动按照带参数GET请求的格式将这两个参数构建到请求地址中。
(3)@POST,@FormUrlEncoded,@Field
@POST("post")
@FormUrlEncoded
fun post(@Field("userName")userName:String, @Field("password")pwd:String):Call<ResponseBody>
这里使用了一个@POST注解,表示当调用post()方法时Retrofit会发起一条POST请求,请求的地址就是我们在@POST注解中传入的具体参数。POST请求如果参数,就需要添加 @FormUrlEncoded注解,表示请求实体是一个表单,每个键值对需要使用@Field注解。
@POST("post")
@FormUrlEncoded
fun post(@Field("userName")userName:String, @Field("password")pwd:String):Call<ResponseBody>
(4) @Path
@POST("{id}")
@FormUrlEncoded
fun postInPath(@Path("id")path:String,@Field("userName")userName:String, @Field("password")pwd:String):Call<ResponseBody>
在POST注解指定的接口地址当中,这里使用了{id}的占位符,然后又在postInPath方法中添加了一个path参数,并使用@Path{”id“}注解来声明这个参数。这样当调用postInPath方法发起请求时,Retrofit会自动将id参数的值替换到占位符的位置,从而组成一个合法的请求地址。
(5)@HTTP
@HTTP(method = "GET", path = "get", hasBody = true)
fun http(@Query("username")userName: String,@Query("password") pwd: String):Call<ResponseBody>
@HTTP注解,通过method设置请求方式(注意大小写),path设置网络请求地址,hasBody是否有请求体。
(6)@Body
@POST("post")
fun postBody(@Body body:RequestBody):Call<ResponseBody>
POST请求并给它加入@Body注解,@Body可以传递自定义类型数据给服务器。如果我们声明参数的类型时会怎样呢?
@POST("post")
fun postBody(@Body body:Data):Call<ResponseBody>
我们在postBody方法中声明Data类型的参数,这样当Retrofit发送POST请求的时候,就会自动将Data对象中的数据转换成JSON格式的文本,并放到HTTP请求的body部分,服务器在收到请求之后只需要将这部分解析出来。
(@Body注解不能与@FormUrlEncoded和@Multiparty一起用)
(7)@Header,@Headers
@Headers("os:android","version:1.0")
@POST("post")
fun postWithHeaders( @Header("a") a:String):Call<ResponseBody>
静态添加header声明,使用 @Headers
动态添加header声明,使用 @Header
(8)@Url
@POST
fun postUrl(@Url url:String):Call<ResponseBody>
@Url注解重写网络接口地址
Retrofit的转换器
在我们接到服务器的相应之后,目前无论是OkHttp还是Retrofit都只能接收到String字符串类型的数据,在实际开发中,我们经常需要对字符串进行解析将其转换为一个对象,比如服务器响应数据为JSON格式字符串,那么我们可以利用GSON库完成发序列化的操作。而Retrofit提供了多个转换器使得响应能够完成自动的数据转换,以JSON解析为例:
添加依赖
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
由于retrofit会借助GSON将JSON数据转换成对象,需要新建一个类
class App(val id:String,val name:String,val price:Double,val imagePath:String) {
}
新建一个接口,获取JSON数据
interface AppService {
@GET("get_JsonArray.json")
fun getAppData(): Call<List<App>>
}
由于这里服务器的接口是HTTP,从Android 9.0系统开始,应用程序默认允许使用HTTPS类型的网络请求,而我用的Apache服务器现在使用的是HTTP,所以要进行网络安全配置。
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.OkhttpRetrofit"
tools:targetApi="31"
android:networkSecurityConfig="@xml/network_config">
新建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>
最后,使用如下代码即可发起Retrofit请求:
val retrofit=Retrofit.Builder()
.baseUrl("http://10.0.2.2/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val appService:AppService=retrofit.create(AppService::class.java)
appService.getAppData().enqueue( object:retrofit2.Callback<List<App>>{
override fun onResponse(
call: retrofit2.Call<List<App>>,
response: retrofit2.Response<List<App>>
) {
val list=response.body()
if(list!=null){
for(a in list){
Log.e("data","id=${a.id} name=${a.name} price=${a.price} imagePath=${a.imagePath}")
}
}
}
override fun onFailure(call: retrofit2.Call<List<App>>, t: Throwable) {
t.printStackTrace()
}
})
文件的上传与下载
上传文件
fun uploadFileTest(){
thread{
try {
val retrofit = Retrofit.Builder().baseUrl("https://www.httpbin.org/").build()
val uploadService: UploadService = retrofit.create(UploadService::class.java)
val file=File(externalCacheDir,"a.txt")
if (!file.exists()){
file.createNewFile();
}
val part:MultipartBody.Part=MultipartBody.Part.createFormData("file",file.name,file.asRequestBody("text/plain".toMediaType()))
val call=uploadService.upload(part)
Log.e("uploadFileTest","${call.execute().body()?.string()}")
}catch (e:Exception){
e.printStackTrace()
}
}
}
下载文件
//下载文件
fun downloadTest(){
thread {
try {
val retrofit = Retrofit.Builder().baseUrl("https://www.httpbin.org/").build()
val uploadService: UploadService = retrofit.create(UploadService::class.java)
val response=uploadService.downloaduri("https://dl2.xmind.cn/Xmind-for-Windows-x64bit-22.11.2677.exe").execute()
val inputStream=response.body()?.byteStream()
val file=openFileOutput("data111",Context.MODE_PRIVATE)
val bis = BufferedInputStream(inputStream)
val buffer = ByteArray(4096)
var len: Int
while (((bis.read(buffer)).also { len = it }) != -1) {
file.write(buffer, 0, len)
}
bis.close()
}catch (e:Exception){
e.printStackTrace()
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95944.html