按钮OnClickListener首次点击返回null,二次点击返回true问题排查
为什么首次点击按钮时jsonArray返回null,第二次才返回正确值?
这问题我之前也碰到过,核心原因是Volley的网络请求是异步执行的,咱们一步步拆解来看:
你当前的代码逻辑里,调用mQueue.add(request)只是把网络请求加入执行队列,但网络请求需要和服务器通信、获取数据,这个过程是需要时间的。而你紧接着就执行了Toast.makeText(...)——这时候onResponse方法还没被触发,jsonArray还是初始的null值,所以首次点击会显示null。
第二次点击按钮时,第一次的网络请求已经完成,onResponse里已经给jsonArray赋值了,所以Toast就能显示出正确的结果。
修复方案1:直接在onResponse内处理数据
这是最简单的解决方式,把需要使用jsonArray的逻辑(比如Toast)放到onResponse方法内部,确保只有当数据成功返回后才执行:
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, ur, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { jsonArray = response.getString("referentiel"); Log.d(TAG, "onResponse() returned: kkkkkk" + jsonArray); // 把Toast移到这里,确保拿到数据后再显示 Toast.makeText(MainActivity.this, "ok"+jsonArray, Toast.LENGTH_LONG).show(); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } }); mQueue.add(request);
修复方案2:用回调接口解耦(适合复杂业务场景)
如果你的业务逻辑需要在onClick方法外处理返回的数据,可以定义一个回调接口来解耦:
// 先定义回调接口 interface OnDataLoadedListener { void onDataLoaded(String data); void onLoadFailed(); } // 按钮点击方法 public void yourButtonOnClick(View view) { JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, ur, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { String jsonData = response.getString("referentiel"); Log.d(TAG, "onResponse() returned: kkkkkk" + jsonData); // 调用回调通知数据加载完成 onDataLoadedListener.onDataLoaded(jsonData); } catch (JSONException e) { e.printStackTrace(); onDataLoadedListener.onLoadFailed(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); onDataLoadedListener.onLoadFailed(); } }); mQueue.add(request); } // 实现回调接口,处理数据 private OnDataLoadedListener onDataLoadedListener = new OnDataLoadedListener() { @Override public void onDataLoaded(String data) { Toast.makeText(MainActivity.this, "ok"+data, Toast.LENGTH_LONG).show(); // 这里还可以添加其他数据处理逻辑 } @Override public void onLoadFailed() { Toast.makeText(MainActivity.this, "数据加载失败", Toast.LENGTH_LONG).show(); } };
额外提醒
- 记得初始化
jsonArray变量(比如赋值为空字符串""),避免空指针异常; - Volley已经自动把
onResponse和onErrorResponse回调切换到主线程执行,所以你可以直接在里面更新UI,不用额外处理线程切换。
内容的提问来源于stack exchange,提问作者Ouertani Saiid
相关产品推荐
相关产品推荐

