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

ArrayMap存2000条数据是否不足?Android加载JSON停滞求助

问题分析与解决方案:加载大JSON文件时应用停滞

首先明确:ArrayMap的容量绝对不是导致停滞的原因,ArrayMap会自动扩容,存储2000条数据完全没有压力。你的应用停滞是因为在UI线程做了大量耗时操作,具体看下面的拆解:

核心问题所在

你在onPostExecute的循环里,每次都执行这样的代码:

textViewProg.setText(textViewProg.getText()+"key : "+ ArrayDati.get(i).Key +"\n"+textViewProg.getText()+"name : "+ ArrayDati.get(i).Name +"\n"+textViewProg.getText()+"code : "+ ArrayDati.get(i).Code );

这里有两个致命问题:

  1. 重复拼接字符串的低效操作:每次循环都要读取当前TextView的文本,再拼接新内容,2000次循环会产生大量临时字符串对象,既耗内存又费时间。
  2. 频繁触发UI重绘:每次调用setText都会让TextView重新渲染界面,2000次重复渲染直接阻塞UI线程,导致应用看起来停滞无响应。

修复步骤

1. 把数据解析移到后台线程(优化性能)

虽然你用了AsyncTask,但之前把JSON解析放在了UI线程的onPostExecute里,其实可以直接在doInBackground里完成解析和数据存储,让UI线程只负责最后一次更新:

// 修改AsyncTask的泛型,返回处理好的ArrayMap
private class JsonCLASS extends AsyncTask<String, Void, ArrayMap<Integer, Valori>> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        caric = new ProgressDialog(MainActivity.this);
        caric.setMessage("Please wait");
        caric.setCancelable(false);
        caric.show();
    }

    @Override
    protected ArrayMap<Integer, Valori> doInBackground(String... params) {
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        ArrayMap<Integer, Valori> tempArray = new ArrayMap<>();
        try {
            URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            InputStream stream = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(stream));
            StringBuffer buffer = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
                Log.d("Response: ", "> " + line);
            }
            // 在这里完成JSON解析,避免占用UI线程
            JSONObject jsonObject = new JSONObject(buffer.toString());
            JSONArray Arr = jsonObject.getJSONArray("clubs");
            for (int i = 0; i < Arr.length(); i++){
                JSONObject jsonPart = Arr.getJSONObject(i);
                tempArray.put(i,new Valori(
                        jsonPart.getString("key"),
                        jsonPart.getString("name"),
                        jsonPart.getString("code")));
            }
            return tempArray;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

2. 优化UI更新逻辑,一次性渲染内容

在onPostExecute里,用StringBuilder高效拼接所有内容,最后只调用一次setText,避免频繁触发UI重绘:

@Override
    protected void onPostExecute(ArrayMap<Integer, Valori> result) {
        super.onPostExecute(result);
        if (result == null) {
            textViewProg.setText("加载失败");
            caric.dismiss();
            return;
        }
        ArrayDati = result;
        StringBuilder sb = new StringBuilder();
        // 一次性拼接所有内容
        for (int i = 0; i < result.size(); i++){
            Valori val = result.get(i);
            sb.append("key : ").append(val.Key).append("\n");
            sb.append("name : ").append(val.Name).append("\n");
            sb.append("code : ").append(val.Code).append("\n\n");
        }
        // 只调用一次setText更新UI
        textViewProg.setText(sb.toString());
        if (caric.isShowing()) {
            caric.dismiss();
        }
    }
}

3. 额外建议:替换废弃的AsyncTask

AsyncTask在Android 11之后已被标记为废弃,推荐用Coroutines(协程)替代,代码更简洁且线程切换更灵活:

// 在onCreate中设置按钮点击事件
buttonProg.setOnClickListener(v -> {
    caric = ProgressDialog.show(MainActivity.this, "", "Please wait", false, false);
    // 开启IO线程处理网络请求和解析
    CoroutineScope(Dispatchers.IO).launch {
        try {
            URL url = new URL("https://raw.githubusercontent.com/openfootball/football.json/master/2015-16/en.1.clubs.json");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            InputStream stream = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            StringBuffer buffer = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            JSONObject jsonObject = new JSONObject(buffer.toString());
            JSONArray Arr = jsonObject.getJSONArray("clubs");
            ArrayMap<Integer, Valori> tempArray = new ArrayMap<>();
            for (int i = 0; i < Arr.length(); i++){
                JSONObject jsonPart = Arr.getJSONObject(i);
                tempArray.put(i,new Valori(
                        jsonPart.getString("key"),
                        jsonPart.getString("name"),
                        jsonPart.getString("code")));
            }
            // 切换到主线程更新UI
            withContext(Dispatchers.Main){
                ArrayDati = tempArray;
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < tempArray.size(); i++){
                    Valori val = tempArray.get(i);
                    sb.append("key : ").append(val.Key).append("\n");
                    sb.append("name : ").append(val.Name).append("\n");
                    sb.append("code : ").append(val.Code).append("\n\n");
                }
                textViewProg.setText(sb.toString());
                caric.dismiss();
            }
        } catch (Exception e) {
            e.printStackTrace();
            withContext(Dispatchers.Main){
                textViewProg.setText("加载失败");
                caric.dismiss();
            }
        }
    }
});

总结

你的问题和ArrayMap容量无关,核心是UI线程中频繁的字符串拼接和UI重绘导致阻塞。通过把数据解析移到后台线程,用StringBuilder一次性拼接内容再更新UI,就能彻底解决应用停滞的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:56:43