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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:50:49