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

使用OkHttp获取谷歌表格数据后,如何正确初始化RecyclerViewAdapter

解决OkHttp请求谷歌Sheets API后RecyclerView适配的两个问题

针对你遇到的两个问题,直接给你可行的代码修改方案和逻辑说明:

问题1:子线程操作UI触发异常

OkHttp的enqueue回调默认在子线程执行,Android不允许在子线程中操作UI组件(包括更新RecyclerView的Adapter)。解决方法是把UI操作切换到主线程,用Activity自带的runOnUiThread方法即可。

问题2:数据未初始化就初始化Adapter触发异常

不要等数据加载完成才初始化Adapter,而是先创建空的数据集和Adapter,后续数据加载完成后再更新数据集并通知Adapter刷新。

修改后的ActivityChoosing核心代码示例

class ActivityChoosing : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: CustomAdapter
    // 用可变列表存储数据,初始为空
    private val dataModels = mutableListOf<YourDataModel>() // 替换成你的实际数据模型类

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_choosing)

        // 初始化RecyclerView和空Adapter
        recyclerView = findViewById(R.id.recycler_view) // 替换成你的RecyclerView ID
        recyclerView.layoutManager = LinearLayoutManager(this)
        adapter = CustomAdapter(dataModels)
        recyclerView.adapter = adapter

        // 启动API请求
        fetchSheetsData()
    }

    private fun fetchSheetsData() {
        val okHttpClient = OkHttpClient()
        val request = Request.Builder()
            .url("你的谷歌Sheets API接口地址")
            .get()
            .build()

        okHttpClient.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                // 请求失败的处理,必须切换到主线程
                runOnUiThread {
                    Toast.makeText(this@ActivityChoosing, "加载失败: ${e.message}", Toast.LENGTH_SHORT).show()
                }
            }

            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
                    response.body?.string()?.let { responseContent ->
                        // 解析API返回的数据到dataModels列表,替换成你的实际解析逻辑
                        val parsedData = parseSheetsResponse(responseContent)
                        
                        // 切换到主线程更新数据和UI
                        runOnUiThread {
                            dataModels.clear()
                            dataModels.addAll(parsedData)
                            adapter.notifyDataSetChanged() // 通知Adapter数据已更新
                        }
                    }
                } else {
                    runOnUiThread {
                        Toast.makeText(this@ActivityChoosing, "请求失败: ${response.code}", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        })
    }

    // 示例解析方法,根据你的Sheets API返回格式实现
    private fun parseSheetsResponse(response: String): List<YourDataModel> {
        // 这里用你习惯的解析方式(Gson/Moshi/手动解析)把JSON转成数据模型列表
        // 比如:return Gson().fromJson(response, object : TypeToken<List<YourDataModel>>() {}.type)
        return emptyList() // 替换成实际解析结果
    }
}

逻辑说明

  1. 提前初始化空Adapter:在onCreate中就创建好Adapter并绑定到RecyclerView,此时dataModels是空的可变列表,不会触发未初始化异常。Adapter持有这个列表的引用,后续数据更新时直接修改列表即可。
  2. 主线程更新UI:所有涉及UI的操作(更新Adapter、Toast提示)都放在runOnUiThread的Lambda中,确保在主线程执行,避免跨线程操作UI的异常。
  3. 数据更新后通知Adapter:当API返回数据并解析完成后,清空原有列表、添加新数据,然后调用adapter.notifyDataSetChanged()让RecyclerView刷新显示新数据。

如果想让列表更新更高效,可以用DiffUtil替代notifyDataSetChanged(),但对于基础场景,notifyDataSetChanged()已经足够解决问题。

内容的提问来源于stack exchange,提问作者Юля Муравьева

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:52:11