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

Kotlin点击Button需两次才可将Volley获取的JSON数据加载到RecyclerView

问题根因与解决方案

你的问题核心是Volley网络请求是异步执行的,当前调用顺序存在时序错误:

  • 点击按钮后先触发jsonParse()发起异步网络请求,紧接着就调用notifyDataSetChanged()刷新列表,此时网络请求还未返回,serviceList还没有新数据,所以第一次刷新无效
  • 等第一次网络请求返回后,serviceList已经被更新,但你没有再触发列表刷新,所以界面没有变化
  • 第二次点击按钮时,触发刷新用的是第一次请求返回的serviceList数据,所以界面才会更新,同时新的请求又会走一遍上面的异步流程,导致永远慢半拍

另外还有两个隐藏问题:

  1. Service数据类构造参数顺序传反,会导致数据展示错位
  2. Volley默认开启请求缓存,修改服务端JSON后第一次请求会命中本地缓存,不会拉取最新数据

具体修改步骤

1. 将Adapter改为MainActivity的成员变量,方便在异步回调中访问

修改MainActivity的变量声明部分:

class MainActivity : AppCompatActivity() {
    private var requestQueue: RequestQueue? = null
    val serviceList: ArrayList<Service> = ArrayList()
    // 新增Adapter作为成员变量
    private lateinit var recycleradapter: Itemadapter
    // ... 其余代码不变

2. 调整Adapter初始化逻辑,删除点击事件中的立即刷新调用

修改onCreate内的代码:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val button: Button = findViewById(R.id.parsebtn)

    // 这里不要加val,直接给成员变量赋值
    recycleradapter = Itemadapter(this, serviceList)
    val recyclerview = findViewById<RecyclerView>(R.id.recycler)
    recyclerview.adapter = recycleradapter
    recyclerview.setHasFixedSize(true)

    button.setOnClickListener {
        // 只需要触发请求,不需要在这里刷新
        jsonParse()
    }
    requestQueue = Volley.newRequestQueue(this)
}

3. 把列表刷新逻辑挪到网络请求成功的回调里,同时修正Service参数顺序

修改jsonParse方法的回调部分:

private fun jsonParse() {
    val url = "MYSERVERIP/test.json"
    val request = JsonObjectRequest(Request.Method.GET, url, null, Response.Listener {
            response ->try {
                serviceList.clear()
                val jsonArray = response.getJSONArray("services")
                for (i in 0 until jsonArray.length()) {
                    val serviceRow = jsonArray.getJSONObject(i)
                    val serviceOrigin = serviceRow.getString("origin")
                    val serviceDestination = serviceRow.getString("destination")
                    val serviceID = serviceRow.getString("train uid")
                    // 修正参数顺序:第一个参数是trainid对应serviceID
                    serviceList.add(Service(serviceID, serviceOrigin, serviceDestination))
                }
                // 解析完所有数据后再刷新列表
                recycleradapter.notifyDataSetChanged()
            } catch (e: JSONException) {
                e.printStackTrace()
            }
    }, {
            error -> error.printStackTrace()
    })
    // 可选:关闭缓存,每次都拉取服务端最新数据
    request.setShouldCache(false)
    requestQueue?.add(request)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:21:03