在现代 Android 应用开发中,网络编程是必不可少的一部分。Retrofit 是 Square 公司推出的一款类型安全的 HTTP 客户端库,简化了与 RESTful API 的交互。Retrofit 基于 OkHttp,并提供了简洁的接口定义和强大的功能,如异步请求、请求拦截、JSON 解析等。本章节将深入讲解 Retrofit 的基本概念、配置、使用方法以及与 OkHttp 的结合,帮助学员掌握 Retrofit 网络请求的实现。
19.1 网络编程概述
19.2 Retrofit 简介
-
Retrofit 的历史与发展:
- Retrofit 是 Square 公司于 2013 年推出的 HTTP 客户端库。
- Retrofit 基于 OkHttp,提供了更简洁的接口定义和更强大的功能。
- Retrofit 2.0 于 2016 年发布,引入了对协程的支持。
-
Retrofit 的优势:
- 类型安全: Retrofit 使用接口定义 API,提供了类型安全的请求和响应。
- 简洁易用: Retrofit 提供了简洁的 API,易于上手和使用。
- 强大的功能: Retrofit 支持异步请求、请求拦截、JSON 解析、文件上传下载等。
- 可扩展性: Retrofit 可以与 OkHttp 拦截器、转换器等结合使用,实现更强大的功能。
- 协程支持: Retrofit 2.6.0 及以上版本支持 Kotlin 协程,简化异步请求代码。
19.3 Retrofit 的基本使用
19.3.1 添加 Retrofit 依赖
在 build.gradle
文件中添加 Retrofit 依赖:
dependencies {implementation "com.squareup.retrofit2:retrofit:2.9.0"implementation "com.squareup.retrofit2:converter-gson:2.9.0"
}
19.3.2 定义 API 接口
使用 Retrofit 的接口定义 API,例如定义一个 GitHub API 接口:
import retrofit2.http.GET
import retrofit2.http.Pathinterface GitHubService {@GET("users/{user}/repos")suspend fun listRepos(@Path("user") user: String): List<Repo>
}data class Repo(val id: Int,@field:SerializedName("name") val name: String,@field:SerializedName("html_url") val url: String
)
19.3.3 创建 Retrofit 实例
使用 Retrofit.Builder 创建 Retrofit 实例,并配置基础 URL 和转换器:
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactoryval retrofit = Retrofit.Builder().baseUrl("https://api.github.com/").addConverterFactory(GsonConverterFactory.create()).build()val service = retrofit.create(GitHubService::class.java)
19.3.4 发起网络请求
使用 Retrofit 发起网络请求,例如获取用户仓库列表:
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launchCoroutineScope(Dispatchers.IO).launch {try {val repos = service.listRepos("octocat")// 处理数据} catch (e: Exception) {// 处理错误}
}
19.4 Retrofit 与 OkHttp 的结合
Retrofit 基于 OkHttp,提供了更强大的功能,例如请求拦截、缓存、重试机制等。
19.4.1 使用 OkHttp Interceptor
OkHttp Interceptor 可以在请求发送前或响应返回后拦截请求和响应,进行自定义处理,例如添加请求头、打印日志等。
-
添加请求头:
import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Responseval headerInterceptor = Interceptor { chain ->val original: Request = chain.request()val requestBuilder = original.newBuilder().header("Accept", "application/json").method(original.method, original.body)val request: Request = requestBuilder.build()chain.proceed(request) }val okHttpClient = OkHttpClient.Builder().addInterceptor(headerInterceptor).build()val retrofit = Retrofit.Builder().baseUrl("https://api.github.com/").client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build()
-
打印日志:
import okhttp3.logging.HttpLoggingInterceptorval loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.level = HttpLoggingInterceptor.Level.BODYval okHttpClient = OkHttpClient.Builder().addInterceptor(loggingInterceptor).build()
19.4.2 使用 OkHttp Cache
OkHttp 提供了缓存机制,可以缓存网络请求结果,提高应用性能。
-
配置缓存:
import okhttp3.Cache import java.io.Fileval cacheSize = 10 * 1024 * 1024 // 10 MB val cacheDirectory = File(context.cacheDir, "http-cache") val cache = Cache(cacheDirectory, cacheSize)val okHttpClient = OkHttpClient.Builder().cache(cache).build()
-
配置缓存策略:
import okhttp3.CacheControlval request = Request.Builder().url("https://api.github.com/users/octocat/repos").cacheControl(CacheControl.Builder().maxStale(1, TimeUnit.DAYS).build()).build()
19.5 Retrofit 进阶功能
19.5.1 文件上传与下载
-
文件上传:
@Multipart @POST("upload") suspend fun uploadFile(@Part file: MultipartBody.Part,@Part("description") description: RequestBody )
-
文件下载:
@GET suspend fun downloadFile(@Url fileUrl: String): ResponseBody// 下载文件 val response = service.downloadFile("https://example.com/file.zip") val file = File(context.filesDir, "file.zip") response.body()?.byteStream()?.use { input ->file.outputStream().use { output ->input.copyTo(output)} }
19.5.2 错误处理
- 自定义异常:
class ApiException(message: String, val code: Int) : Exception(message)// 解析错误 try {val response = service.getData()if (response.isSuccessful) {// 处理成功} else {throw ApiException("API Error", response.code())} } catch (e: ApiException) {// 处理 API 异常 } catch (e: Exception) {// 处理其他异常 }
19.6 实战案例
-
案例一:使用 Retrofit 实现 GitHub API 请求
- 定义 GitHub API 接口。
- 创建 Retrofit 实例。
- 使用协程发起网络请求,获取用户仓库列表。
- 在 Activity 中显示仓库列表。
-
案例二:使用 Retrofit 实现文件上传
- 定义文件上传 API 接口。
- 使用 Retrofit 上传文件。
- 在 Activity 中选择文件并上传。
-
案例三:使用 Retrofit 实现文件下载
- 定义文件下载 API 接口。
- 使用 Retrofit 下载文件。
- 在 Activity 中下载文件并保存到内部存储。
19.7 课后作业
-
任务一:使用 Retrofit 实现 GitHub API 请求
- 定义 GitHub API 接口。
- 创建 Retrofit 实例。
- 使用协程发起网络请求,获取用户仓库列表。
- 在 Activity 中显示仓库列表。
-
任务二:使用 Retrofit 实现文件上传
- 定义文件上传 API 接口。
- 创建 Retrofit 实例。
- 使用协程发起文件上传请求。
- 在 Activity 中选择文件并上传。
-
任务三:使用 Retrofit 实现文件下载
- 定义文件下载 API 接口.
- 创建 Retrofit 实例.
- 使用协程发起文件下载请求.
- 在 Activity 中下载文件并保存到内部存储.
通过本章节的学习,学员将能够掌握 Retrofit 网络请求的基本概念、使用方法以及与 OkHttp 的结合,并能够使用 Retrofit 实现各种网络请求操作,包括 GET, POST, 文件上传下载等。