[Android]网络框架之Retrofit(kotlin)

简介: [Android]网络框架之Retrofit(kotlin)

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()
           }
       }
    }
目录
相关文章
|
16天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
18天前
|
数据库 Android开发 开发者
构建高效Android应用:Kotlin协程的实践指南
【4月更文挑战第2天】随着移动应用开发的不断进步,开发者们寻求更流畅、高效的用户体验。在Android平台上,Kotlin语言凭借其简洁性和功能性赢得了开发社区的广泛支持。特别是Kotlin协程,作为一种轻量级的并发处理方案,使得异步编程变得更加简单和直观。本文将深入探讨Kotlin协程的核心概念、使用场景以及如何将其应用于Android开发中,以提高应用性能和响应能力。通过实际案例分析,我们将展示协程如何简化复杂任务,优化资源管理,并为最终用户提供更加流畅的体验。
|
18天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
23天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
在开发高性能的Android应用时,选择合适的编程语言至关重要。近年来,Kotlin因其简洁性和功能性受到开发者的青睐,但其性能是否与传统的Java相比有所不足?本文通过对比分析Kotlin与Java在Android平台上的运行效率,揭示二者在编译速度、运行时性能及资源消耗方面的具体差异,并探讨在实际项目中如何做出最佳选择。
17 4
|
2天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
5 0
|
4天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android&#39;s AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
5 0
|
4天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
5 0
|
8天前
|
网络协议 Java API
Python网络编程基础(Socket编程)Twisted框架简介
【4月更文挑战第12天】在网络编程的实践中,除了使用基本的Socket API之外,还有许多高级的网络编程库可以帮助我们更高效地构建复杂和健壮的网络应用。这些库通常提供了异步IO、事件驱动、协议实现等高级功能,使得开发者能够专注于业务逻辑的实现,而不用过多关注底层的网络细节。
|
12天前
|
移动开发 API Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第7天】 在移动开发领域,性能优化和应用响应性的提升一直是开发者追求的目标。近年来,Kotlin语言因其简洁性和功能性在Android社区中受到青睐,特别是其对协程(Coroutines)的支持,为编写异步代码和处理并发任务提供了一种更加优雅的解决方案。本文将探讨Kotlin协程在Android开发中的应用,揭示其在提高应用性能和简化代码结构方面的潜在优势,并展示如何在实际项目中实现和优化协程。
|
存储 设计模式 网络协议
Netty网络框架(一)
Netty网络框架
30 1