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

使用Volley请求加密货币数据遇解析错误,寻求解决及数据提取方法

解决Volley解析加密货币接口数据的问题 + ListView展示方案

先纠正一个小误解:你提到的加密货币接口返回的是JSONObject结构,而非JSONArray,所以应该用JsonObjectRequest来替代StringRequest(或者用StringRequest但手动转JSON,不过前者更省心),这应该就是你遇到解析错误的核心原因。

下面是一步步的解决方案:

1. 用JsonObjectRequest替代StringRequest处理接口请求

首先确保你已经在项目中引入Volley依赖,然后编写请求代码:

// 建议在Application类中全局初始化RequestQueue,避免重复创建实例
RequestQueue requestQueue = Volley.newRequestQueue(context);

String apiUrl = "https://min-api.cryptocompare.com/data/all/coinlist";

JsonObjectRequest jsonRequest = new JsonObjectRequest(
        Request.Method.GET,
        apiUrl,
        null, // GET请求无需请求体,传null即可
        response -> {
            // 成功获取响应,在这里解析数据
            try {
                // 接口核心数据都嵌套在"Data"字段下
                JSONObject dataContainer = response.getJSONObject("Data");
                
                // 通过币种键值直接获取对应数据,比如BTC、ETH、LTC
                JSONObject btcInfo = dataContainer.getJSONObject("BTC");
                JSONObject ethInfo = dataContainer.getJSONObject("ETH");
                JSONObject ltcInfo = dataContainer.getJSONObject("LTC");
                
                // 把解析出的字段封装到自定义模型类,方便后续ListView展示
                CryptoCoin btc = new CryptoCoin(
                        btcInfo.getString("CoinName"),
                        btcInfo.getString("Symbol"),
                        btcInfo.getString("ImageUrl")
                        // 可按需添加其他字段,比如Description、TotalSupply等
                );
                // 同理处理ETH和LTC数据...
                
                // 把数据集合传给ListView进行展示
                setupCryptoListView(Arrays.asList(btc, eth, ltc));
                
            } catch (JSONException e) {
                e.printStackTrace();
                Toast.makeText(context, "数据解析失败", Toast.LENGTH_SHORT).show();
            }
        },
        error -> {
            // 请求失败的处理逻辑
            if (error.networkResponse != null) {
                Log.e("VolleyError", "请求状态码:" + error.networkResponse.statusCode);
            }
            Toast.makeText(context, "获取数据失败,请检查网络", Toast.LENGTH_SHORT).show();
        }
);

// 将请求加入队列执行
requestQueue.add(jsonRequest);

2. 自定义币种数据模型类

创建一个CryptoCoin类来封装币种信息,让Adapter更易处理:

public class CryptoCoin {
    private String coinName;
    private String symbol;
    private String imageUrl;

    public CryptoCoin(String coinName, String symbol, String imageUrl) {
        this.coinName = coinName;
        this.symbol = symbol;
        this.imageUrl = imageUrl;
    }

    // Getter方法
    public String getCoinName() { return coinName; }
    public String getSymbol() { return symbol; }
    public String getImageUrl() { return imageUrl; }
}

3. 自定义ListView Adapter

编写继承自BaseAdapter的自定义适配器,用来渲染列表项:

public class CryptoListAdapter extends BaseAdapter {
    private List<CryptoCoin> coinList;
    private Context context;

    public CryptoListAdapter(Context context, List<CryptoCoin> coinList) {
        this.context = context;
        this.coinList = coinList;
    }

    @Override
    public int getCount() {
        return coinList.size();
    }

    @Override
    public Object getItem(int position) {
        return coinList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.item_crypto, parent, false);
            holder = new ViewHolder();
            holder.tvCoinName = convertView.findViewById(R.id.tv_coin_name);
            holder.tvSymbol = convertView.findViewById(R.id.tv_symbol);
            holder.ivCoinIcon = convertView.findViewById(R.id.iv_coin_icon);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        CryptoCoin currentCoin = coinList.get(position);
        holder.tvCoinName.setText(currentCoin.getCoinName());
        holder.tvSymbol.setText(currentCoin.getSymbol());
        
        // 加载币种图标,需拼接完整路径(接口返回的是相对路径)
        Glide.with(context)
                .load("https://www.cryptocompare.com" + currentCoin.getImageUrl())
                .into(holder.ivCoinIcon);

        return convertView;
    }

    // 复用ViewHolder提升列表性能
    static class ViewHolder {
        TextView tvCoinName;
        TextView tvSymbol;
        ImageView ivCoinIcon;
    }
}

4. 绑定数据到ListView

在Activity/Fragment中初始化ListView并设置适配器:

private void setupCryptoListView(List<CryptoCoin> coinList) {
    ListView cryptoListView = findViewById(R.id.lv_crypto_list);
    CryptoListAdapter adapter = new CryptoListAdapter(this, coinList);
    cryptoListView.setAdapter(adapter);
    
    // 可选:添加列表项点击事件
    cryptoListView.setOnItemClickListener((parent, view, position, id) -> {
        CryptoCoin selectedCoin = coinList.get(position);
        Toast.makeText(this, "你选择了:" + selectedCoin.getCoinName(), Toast.LENGTH_SHORT).show();
    });
}

关键注意事项

  • 记得在AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" />
  • 接口返回的ImageUrl是相对路径,必须拼接前缀https://www.cryptocompare.com才能加载完整图标
  • 如果需要批量处理更多币种,可以把符号放到数组中循环遍历dataContainer,避免重复代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:44:29