使用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
相关产品推荐
相关产品推荐

