每次新建Android项目,选网络库就像在奶茶店点单——Retrofit是经典珍珠奶茶稳中求胜,Ktor是新出的芝士葡萄鲜果茶让人跃跃欲试。
- 当你急着对接API时,哪个能三分钟搞定?
- 当产品经理突发奇想要加WebSocket时,哪个能优雅接招?
- 当老板说要搞跨平台开发时,哪个能让你少掉头发?
举个栗子
Retrofit基础用法
// 1. 定义接口(就像点菜单)
interface NewsApiService {
@GET("news/latest")
suspendfun getLatestNews(): Response<List<News>>
}
// 2. 创建Retrofit实例(配菜过程)
val retrofit = Retrofit.Builder()
.baseUrl("https://api.rairmmd.com/")
.addConverterFactory(GsonConverterFactory.create()) // 自动把JSON变成对象
.client(OkHttpClient.Builder().addInterceptor(HttpLoggingInterceptor()).build())
.build()
// 3. 开始点菜!
val service = retrofit.create(NewsApiService::class.java)
val newsList = service.getLatestNews().body() // 直接拿到新闻列表对象
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
适合场景:快速对接标准REST API
Ktor简单配置
// 1. 创建客户端(搭积木式配置)
val httpClient = HttpClient(CIO) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true// JSON多了字段也不报错
})
}
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.HEADERS // 想看请求头就调这个
}
}
// 2. 发起请求(像发微信一样简单)
suspendfun fetchNews(): List<News> {
return httpClient.get("https://api.rairmmd.com/news/latest").body()
}
// 3. 高级玩法:动态URL参数
val searchResults = httpClient.get {
url("https://api.rairmmd.com/search")
parameter("q", "热门") // 自动拼接到URL
parameter("page", 2)
}.body<List<Article>>()
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
亮点功能:想加什么功能就像装插件,比如给请求自动加Token:
HttpClient {
install(Auth) {
bearer {
loadTokens {
BearerTokens("token", "1122334455667788")
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
实例对比
案例1:新闻列表接口(Retrofit版)
// 接口定义
@GET("newsList")
suspendfun getNewsListByCategory(
@Query("category") category: String,
@Query("page") page: Int
): Response<NewsResponse>
// 使用方式
viewModelScope.launch {
try {
val response = newsService.getNewsListByCategory("热门", 1)
if (response.isSuccessful) {
_newsList.value = response.body()?.data ?: emptyList()
}
} catch (e: Exception) {
// 处理异常
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
案例2:同一个功能(Ktor版)
suspend fun loadNewsList(category: String, page: Int) {
val result = httpClient.get {
url("https://api.rairmmd.com/newsList")
parameters {
append("category", category)
append("page", page.toString())
}
}
if (result.status == HttpStatusCode.OK) {
val newsData = result.body<NewsResponse>()
_newsList.value = newsData.data
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
选择困难症急救包
当你需要...
- 快速上线 → Retrofit(老司机踩油门)
// 三行代码搞定基础配置
Retrofit.Builder()
.baseUrl("https://api.rairmmd.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
- 1.
- 2.
- 3.
- 4.
- 5.
- 魔改请求 → Ktor(乐高式组装)
// 自定义超时时间+重试机制
HttpClient(CIO) {
install(HttpTimeout) {
requestTimeoutMillis = 15000
}
install(HttpRequestRetry) {
maxRetries = 3
retryOnExceptionIf { _, cause ->
cause is ConnectTimeoutException
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 跨平台开发 → Ktor(一份代码走天下)
// 共享common模块中的网络请求代码
expect fun createHttpClient(): HttpClient
// iOS版实现
actual fun createHttpClient() = HttpClient(CIO) { /* iOS配置 */ }
// Android版实现
actual fun createHttpClient() = HttpClient(Android) { /* Android配置 */ }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
过来人的忠告
Retrofit踩坑记录
// 坑1:忘记加转换器会直接崩溃!
Retrofit.Builder()
.baseUrl("https://api.rairmmd.com/")
// 漏了.addConverterFactory()
.build()
// 坑2:路径参数要用@Path标注
@GET("user/{id}/profile") // ✅ 正确姿势
suspend fun getUserProfile(@Path("id") userId: String)
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
Ktor避雷指南
// 雷区1:协程作用域没管理好
// 错误示范 ❌
fun loadData() {
GlobalScope.launch {
httpClient.get(...) // 可能导致内存泄漏
}
}
// 正确姿势 ✅
viewModelScope.launch {
httpClient.get(...)
}
// 雷区2:响应解析类型不匹配
val news = httpClient.get("...").body<News>() // News类字段要和JSON完全对应
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
终极选择器
需求 | Retrofit | Ktor |
要对接10个API且今晚就要上线 | 👍 稳如老狗 | 👎 现学来不及 |
要做直播间的弹幕推送 | 👎 轮询费劲 | 👍 长连接神器 |
老板说要"技术前沿" | 👴 经典款 | 🚀 新潮之选 |
团队全是Java老手 | 👨💻 无缝衔接 | 🤯 语法震惊 |
想做小程序+APP+网页三端通吃 | ❌ 各玩各的 | 🌍 跨平台大法 |
小项目随便选,大项目看团队。实在纠结?