Kotlin点击Button需两次才可将Volley获取的JSON数据加载到RecyclerView
问题根因与解决方案
你的问题核心是Volley网络请求是异步执行的,当前调用顺序存在时序错误:
- 点击按钮后先触发
jsonParse()发起异步网络请求,紧接着就调用notifyDataSetChanged()刷新列表,此时网络请求还未返回,serviceList还没有新数据,所以第一次刷新无效 - 等第一次网络请求返回后,
serviceList已经被更新,但你没有再触发列表刷新,所以界面没有变化 - 第二次点击按钮时,触发刷新用的是第一次请求返回的
serviceList数据,所以界面才会更新,同时新的请求又会走一遍上面的异步流程,导致永远慢半拍
另外还有两个隐藏问题:
- Service数据类构造参数顺序传反,会导致数据展示错位
- 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
相关产品推荐
相关产品推荐

