(十八)安卓开发中的网络请求实战:从Retrofit到协程的接口调用演进

1. 网络请求的“石器时代”与“工业革命”

我记得刚入行安卓开发那会儿,处理网络请求简直就是一场噩梦。那时候最常用的就是 HttpURLConnection,你得自己手动拼接URL,处理输入输出流,还得小心翼翼地管理线程,生怕一不小心就在主线程做了网络操作,导致应用卡顿甚至崩溃。后来出现了 AsyncTask,感觉像是救星,但用久了才发现,它带来的内存泄漏问题和复杂的生命周期管理,简直是埋下了无数个“定时炸弹”。那时候写一个简单的网络请求,代码量能绕地球半圈,逻辑还特别容易绕晕。

直到 Retrofit 的出现,我才真正体会到什么叫“工业革命”。它把网络请求从繁琐的底层细节中解放出来,让你能用声明接口的方式去定义API,就像在跟服务器“对话”一样自然。它底层基于强大的 OkHttp,但做了更高层次的抽象。我打个比方,以前你用 HttpURLConnection 就像自己从零开始造一辆自行车,每个零件都得自己打磨;而 Retrofit 给了你一套精密的乐高积木,你只需要按照图纸(接口定义)拼装,就能得到一辆功能齐全、性能优异的跑车。

在咱们这个新闻资讯App的场景里,需求很明确:从一个服务器接口获取新闻列表,然后展示在 RecyclerView 里。如果用老方法,光是处理JSON解析和线程切换就够头疼的。但用 Retrofit,整个过程变得异常清晰。首先,你定义一个接口,告诉它:“嘿,我要用GET方法访问 /news 这个路径,返回的数据格式是 NewsListResponse。” 然后,Retrofit 就会帮你处理好一切:构建请求、发送、接收响应、解析JSON。你只需要关心“要什么”和“拿到后干什么”,中间的脏活累活它全包了。这种转变不仅仅是代码量的减少,更是开发思维的一次升级,让你能更专注于业务逻辑本身。

2. Retrofit + 回调:经典模式的得与失

虽然 Retrofit 极大地简化了网络请求,但在早期,我们主要配合它的 CallCallback 进行异步回调。这套模式在当时已经非常先进了,但用久了,尤其是在复杂的业务逻辑里,它的“坑”也开始显现。咱们还是以新闻App为例,一步步拆解。

2.1 基础搭建:依赖、接口与模型

第一步永远是引入依赖。现在 Retrofit 已经更新了不少版本,我建议直接用较新的稳定版。在 app 模块的 build.gradle 文件里添加:

dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.google.code.gson:gson:2.10.1'
}

这里 converter-gson 是核心,它负责把服务器返回的JSON字符串自动转换成我们定义的Kotlin数据类。接下来,定义我们的数据模型。假设服务器返回的新闻列表数据格式如下:

{
  "code": 0,
  "message": "success",
  "data": {
    "page": 1,
    "list": [
      {
        "id": "1001",
        "title": "AI技术新突破",
        "summary": "研究人员在自然语言处理领域取得重大进展...",
        "coverUrl": "https://example.com/image1.jpg",
        "publishTime": "2023-10-27 10:30:00"
      }
    ]
  }
}

那么对应的Kotlin数据类可以这样写:

// 最外层的响应包装
data class ApiResponse<T>(
    val code: Int,
    val message: String,
    val data: T?
)

// 分页数据包装
data class NewsListData(
    val page: Int,
    val list: List<NewsItem>
)

// 单条新闻数据
data class NewsItem(
    val id: String,
    val title: String,
    val summary: String,
    @SerializedName("coverUrl") // 使用注解处理字段名不一致的情况
    val coverUrl: String,
    val publishTime: String
)

注意 @SerializedName 注解,这是Gson提供的,当JSON字段名和Kotlin属性名不一致时(比如驼峰和下划线),用它来建立映射关系。模型定义好后,就可以定义API接口了:

interface NewsApiService {
    @GET("news/list")
    fun fetchNewsList(@Query("page") page: Int): Call<ApiResponse<NewsListData>>
}

@GET 注解表明这是一个GET请求,参数 page 通过 @Query 注解以查询参数的形式附加到URL上。返回值 Call<ApiResponse<NewsListData>>Retrofit 回调模式的核心,它代表一个等待执行的网络请求。

2.2 发起请求与处理回调

ActivityViewModel 中,我们需要创建 Retrofit 实例并发起请求:

class NewsActivity : AppCompatActivity() {
    private lateinit var newsAdapter: NewsAdapter
    private val newsList = mutableListOf<NewsItem>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_news)
        // ... 初始化RecyclerView和Adapter
        loadNews(1)
    }

    private fun loadNews(page: Int) {
        // 1. 创建Retrofit实例
        val retrofit = Retrofit.Builder()
            .baseUrl("https://your-api-server.com/") // 你的服务器地址
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值