AsyncHttpClient异步请求中ID获取异常问题求助
问题根源与解决方案
你遇到的核心问题是异步请求的闭包变量捕获陷阱,再加上全局变量被异步请求覆盖导致的ID混乱,我们一步步拆解解决:
为什么总是拿到最后一个ID?
你的showTrajects循环调用AllPendingTrajects()时,AsyncHttpClient的get请求是异步执行的——循环会先跑完所有迭代,而此时所有请求的回调还没触发。因为闭包会共享循环变量indexTrajecte,等回调执行时,indexTrajecte已经变成了循环的最后一个值,所以所有请求都会使用这个最后索引对应的ID。
另外,全局变量idTraject会被多个并发的异步请求覆盖,后完成的请求会把先完成的请求的ID覆盖掉,导致SeeAllTrajects()里拿到的是随机(实际是最后完成的)ID。
修复方案
1. 捕获循环的当前索引值,避免闭包共享
在循环中创建局部变量保存当前迭代的索引,让每个异步请求的回调捕获独立的变量值;同时把请求对应的ID作为参数传递,不再依赖全局变量。
修改showTrajects和AllPendingTrajects:
public void showTrajects() { for (int indexTrajecte = 0; indexTrajecte < contador; indexTrajecte++) { // 用局部变量捕获当前循环的索引,每个迭代的变量都是独立的 final int currentIndex = indexTrajecte; AllPendingTrajects(currentIndex); } } public void AllPendingTrajects(final int currentIndex){ AsyncHttpClient client = new AsyncHttpClient(); // 使用当前索引对应的ID,而非共享的循环变量 String URL = "http://url.net/api/link1/"+IDTrajecte[currentIndex]; client.get(URL, new AsyncHttpResponseHandler() { @Override public void onStart() {} @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { JSONObject trajectes = new JSONObject(); String strResponseBody = new String(responseBody); try { trajectes = new JSONObject(strResponseBody); } catch (JSONException e) { Toast.makeText(PendingTrajectRecyclerView.this, "Error", Toast.LENGTH_SHORT).show(); } try { JSONArray realitzas = trajectes.getJSONArray("realitzas"); dniTaxista = trajectes.getString("taxistes_dni"); // 保存当前请求对应的ID,不使用全局变量 final int currentTrajectId = Integer.parseInt(trajectes.getString("ID")); if(DadesTaxista.DNI.equals(dniTaxista)){ showPendingTraject(); } else { // 把当前ID传递给SeeAllTrajects SeeAllTrajects(currentTrajectId); } } catch (JSONException e) { e.printStackTrace(); } } @Override public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody, Throwable error) { Log.d("ERROR",""+statusCode); } }); }
2. 修改SeeAllTrajects,接收独立的ID参数
不再依赖全局变量,直接使用传递过来的当前请求ID:
public void SeeAllTrajects(final int currentTrajectId){ AsyncHttpClient client = new AsyncHttpClient(); String URL = "http://url.net/api/link2"; client.get(URL, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { JSONArray trajectesJSON = new JSONArray(); String strResponseBody = new String(responseBody); try { trajectesJSON = new JSONArray(strResponseBody); } catch (JSONException e) { Toast.makeText(PendingTrajectRecyclerView.this, "Error", Toast.LENGTH_SHORT).show(); } try { // 使用传递过来的独立ID,不再受全局变量覆盖影响 Log.d("ID TRAJECT:", "d" + currentTrajectId); } catch (Exception e) { e.printStackTrace(); } } @Override public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody, Throwable error) { Log.d("ERROR",""+statusCode); } }); }
额外建议
如果项目允许的话,建议替换成更现代的异步请求框架(比如Retrofit),配合Kotlin协程或者Java的CompletableFuture,可以彻底避免这类回调陷阱,代码可读性也会更高。
内容的提问来源于stack exchange,提问作者Luis
相关产品推荐
相关产品推荐

