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

Android中Volley+JsonObjectRequest回调传数据至Activity失败求助

解决Volley异步请求回调无法传递数据到Activity的问题

我来帮你排查下这个回调失效的问题,看了你的代码,主要有几个关键细节没处理好,导致Activity接收不到请求回来的数据,咱们一步步理顺:

问题根源分析

  1. 异步请求的时序问题:Volley的网络请求是异步执行的,你调用getMarketSummary后立刻执行adapter.notifyDataSetChanged(),这时候请求还在后台跑,数据根本没回来;而且你试图通过return listCoins获取结果也是无效的——因为return的时候请求还没完成,listCoins还是空的。
  2. 回调被多次触发:你在每个请求的onResponse里都调用callback.onSuccess(listCoins),但这时候listCoins还在被多个请求填充,会导致Activity多次接收不完整的数据,后续请求还会覆盖之前的状态。
  3. Coin对象复用导致数据混乱:循环里你把this.coin = coinAux,然后在异步回调里修改这个对象——因为Volley请求是并发的,循环里的coinAux会被快速覆盖,最终所有请求都会修改同一个Coin实例,数据完全乱掉。

修正后的代码实现

第一步:修改请求类的getMarketSummary方法

把返回值改成void(异步请求靠回调传结果,return毫无意义),添加请求计数器确保所有请求完成后再回调,同时每个请求使用独立的Coin对象:

public void getMarketSummary(final DashboardActivity.CoinCallback callback, ArrayList<Coin> listAux, Context context) {
    Log.d("chegamos a entrar en getCOinData??", "Entramos en getMarketSummary");
    listCoins.clear();
    requestQueue = Volley.newRequestQueue(context);
    // 统计需要执行的总请求数
    final int totalRequests = listAux.size();
    int completedRequests = 0;

    for (Coin coinAux : listAux) {
        if (!coinAux.getShortName().equals("BTC")) {
            // 复制原Coin对象,避免并发修改同一个实例
            Coin coin = new Coin();
            // 这里手动复制coinAux的所有属性到新对象(根据你的Coin类实际属性调整)
            coin.setShortName(coinAux.getShortName());
            coin.setName(coinAux.getName());
            // 其他需要保留的属性都复制过来...

            String urlMarket = "https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-SHORTNAME";
            String coinShortName = coin.getShortName();
            urlMarket = urlMarket.replaceAll("SHORTNAME", coinShortName.toLowerCase());

            JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, urlMarket, null,
                    new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            try {
                                JSONArray result = response.getJSONArray("result");
                                if (result.length() > 0) {
                                    JSONObject data = result.getJSONObject(0);
                                    coin.setHigh(Double.parseDouble(data.getString("High")));
                                    coin.setLow(Double.parseDouble(data.getString("Low")));
                                    coin.setLast(Double.parseDouble(data.getString("Last")));
                                    coin.setVolInBtc(Double.parseDouble(data.getString("BaseVolume")));
                                    coin.setBid(Double.parseDouble(data.getString("Bid")));
                                    coin.setAsk(Double.parseDouble(data.getString("Ask")));
                                    coin.setPrevDay(data.getString("PrevDay"));
                                    listCoins.add(coin);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                completedRequests++;
                                // 所有请求完成后统一回调Activity
                                if (completedRequests == totalRequests) {
                                    callback.onSuccess(listCoins);
                                }
                            }
                        }
                    }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    error.printStackTrace();
                    completedRequests++;
                    // 即使请求失败,也要计数,确保最终能回调
                    if (completedRequests == totalRequests) {
                        callback.onSuccess(listCoins);
                    }
                }
            });
            requestQueue.add(request);
        } else {
            // BTC直接加入列表,计数加1
            listCoins.add(coinAux);
            completedRequests++;
            if (completedRequests == totalRequests) {
                callback.onSuccess(listCoins);
            }
        }
    }
}

第二步:修正Activity的回调逻辑

Volley的回调是在子线程执行的,必须切换到主线程更新UI,同时把adapter.notifyDataSetChanged()移到回调里(这时候数据才准备好):

public void initCallback() {
    this.coinCallback = new CoinCallback() {
        @Override
        public void onSuccess(ArrayList<Coin> coinListFromRequest) {
            // 切换到主线程更新UI
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    coinList = coinListFromRequest;
                    adapter.notifyDataSetChanged(); // 这里才是更新UI的正确时机
                }
            });
        }
    };
}

第三步:修改请求调用方式

不再接收返回值,因为异步请求的结果只能通过回调获取:

// 只需要发起请求,结果靠回调处理
bittrexAPIRequest.getMarketSummary(coinCallback, coinList, this);
// 不要在这里调用notifyDataSetChanged,数据还没回来!

关键说明

  • 计数器的作用:确保所有请求(包括成功和失败的)都处理完毕后,再把完整的listCoins传递给Activity,避免多次回调导致数据不完整。
  • 独立Coin对象:每个请求使用新的Coin实例,避免并发请求修改同一个对象导致数据混乱。
  • 主线程更新UI:Android不允许在子线程更新UI,所以必须用runOnUiThread包裹UI操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:19:30