You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Retrofit调用API后RecyclerView数据不更新问题排查

RecyclerView调用notifyDataSetChanged()不更新的问题解决

问题原因

  1. UI更新线程错误:RecyclerView的通知更新操作必须在主线程执行,你当前在Dispatchers.Default后台协程中调用notifyDataSetChanged(),导致更新指令无法被UI线程处理,列表自然不会刷新。
  2. 潜在空指针风险:异步API请求如果意外提前返回(如缓存命中),可能会出现orderAdapter尚未初始化就调用!!强制解包的情况,引发崩溃。

解决方案

1. 强制在主线程执行UI更新

使用withContext(Dispatchers.Main)将notifyDataSetChanged()包裹,确保更新操作在主线程运行。

2. 优化数据更新逻辑

给适配器添加封装的updateData方法,内部处理列表替换和通知,避免直接操作数据源的强制类型转换,同时降低空指针风险。

3. 替换GlobalScope(推荐)

GlobalScope的生命周期不受Activity管理,易引发内存泄漏,改用lifecycleScope(需依赖androidx.lifecycle:lifecycle-runtime-ktx)绑定Activity生命周期。

修正后的代码

主Activity代码

class OrderHistoryActivity : AppCompatActivity() {
    lateinit var recyclerView: RecyclerView
    var orderAdapter: OrderAdapter? = null
    var models: MutableList<OrderModel> = ArrayList() // 直接初始化,避免可空
    lateinit var prefs: Prefs

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_order_history)
        recyclerView = findViewById(R.id.orderRecyclerView)
        prefs = Prefs(this@OrderHistoryActivity)

        // 初始化静态测试数据
        for (i in 0..7) {
            models.add(OrderModel("#14524$i", "Nov 3, 2022", "Completed"))
        }

        // 初始化RecyclerView与适配器
        recyclerView.layoutManager = LinearLayoutManager(this)
        orderAdapter = OrderAdapter(this, models)
        recyclerView.adapter = orderAdapter
        Log.d("FUNCTION", "RESULT -> STATIC DATA")

        // 使用lifecycleScope发起异步请求,绑定Activity生命周期
        lifecycleScope.launch(Dispatchers.IO) {
            runCatching {
                Log.d("FUNCTION", "API TO GET ORDERS INIT ${prefs.token} ${prefs.userId}")
                val response = withTimeout(REST_API_TIMEOUT) {
                    RetrofitClient(this@OrderHistoryActivity).getApi().getOrders(
                        prefs.token, prefs.userId, "get"
                    ).execute().parseResult<OrdersResponse>()
                }

                Log.d("FUNCTION", "API TO GET RESULTS -> RESPONSE ${Gson().toJson(response)} ")
                response.lastReadDate = System.currentTimeMillis()

                // 转换API数据为OrderModel列表
                val newOrders = mutableListOf<OrderModel>()
                response.data.forEach { data ->
                    val orderId = data.id
                    val orderStatus = data.status
                    Log.d("FUNCTION", "API TO GET IND RESULT -> RESPONSE ${orderId} ${orderStatus}")
                    newOrders.add(OrderModel("${orderId}", "Nov 20, 2024", "${orderStatus}"))
                }

                // 切换到主线程更新UI
                withContext(Dispatchers.Main) {
                    models.clear()
                    models.addAll(newOrders)
                    orderAdapter?.notifyDataSetChanged() // 使用安全调用避免空指针
                    Log.d("FUNCTION", "API TO GET IND RESULT MODELS -> RESPONSE ${models}")
                }
            }.onFailure { ex ->
                when (ex) {
                    is RestApiException -> {
                        val err = OnApiErrorEvent(ex.message ?: ex.toString())
                        Log.d("FUNCTION", "rest exp")
                        Log.d("FUNCTIONwwr", "${err}")
                    }
                    is CancellationException -> {
                        // 处理请求超时逻辑
                    }
                    else -> {
                        val err = OnApiErrorEvent(ex.message ?: ex.toString())
                        // 处理其他异常逻辑
                    }
                }
            }.finally {
                withContext(Dispatchers.Main) {
                    // viewModel.progress.set(false)
                }
            }
        }
    }
}

适配器优化(可选)

给OrderAdapter添加封装的更新方法,让数据更新更安全优雅:

class OrderAdapter(private val context: Context, private val orders: MutableList<OrderModel>) :
    RecyclerView.Adapter<OrderAdapter.ViewHolder>() {

    // ... 保留原有的ViewHolder、onCreateViewHolder、onBindViewHolder、getItemCount实现

    // 封装数据更新方法
    fun updateData(newOrders: List<OrderModel>) {
        orders.clear()
        orders.addAll(newOrders)
        notifyDataSetChanged()
    }
}

此时Activity主线程的更新代码可替换为:

orderAdapter?.updateData(newOrders)

内容的提问来源于stack exchange,提问作者user1001176

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:23:15