AsyncTask中生成的ArrayList无法填充ListView问题解决方案
问题根因
你在AsyncTask的子线程中完成网络请求、JSON解析、数据插入集合的逻辑后,没有通知绑定ListView的适配器数据已更新,适配器不会主动重新拉取集合数据渲染界面,这是异步加载数据后列表不显示的核心原因。
补充说明:你在onCreate中手动添加数据能正常显示,是因为setAdapter执行时集合里已经存在数据,适配器首次初始化就能拿到正确的数据集长度和内容;而异步任务的网络请求存在耗时,等数据插入集合时适配器早就完成了首次渲染,没收到刷新通知自然不会更新界面。
另外你代码里还有三个小问题:
- 网络连接、输入流没有在finally块统一释放,日志里的
A resource failed to call close警告就是资源泄漏导致的 - AsyncTask里把
name/height/mass定义成了类成员变量,循环复用时如果出现并发容易出现数据错乱 - 日志拼接时name和height之间没加空格,打印内容会连在一起
修复方法
- 给
CharacterGetData重写onPostExecute方法,这个方法会在doInBackground执行完成后自动切回主线程,在方法内调用适配器的notifyDataSetChanged()方法,通知列表刷新即可。 - 把流、连接的释放逻辑移到finally块,避免资源泄漏。
- 把循环内用到的
name/height/mass变量移到for循环内部声明,避免值覆盖问题。
修正后的核心代码
// 仅贴修改后的AsyncTask部分,其余代码不需要改动 class CharacterGetData extends AsyncTask<String, Integer, String> { @Override protected String doInBackground(String... strings) { HttpURLConnection connection = null; BufferedReader in = null; try { URL obj = new URL("https://swapi.dev/api/people/?format=json"); connection = (HttpURLConnection) obj.openConnection(); connection.setRequestMethod("GET"); in = new BufferedReader( new InputStreamReader(connection.getInputStream())); String line; StringBuffer response = new StringBuffer(); while ((line = in.readLine()) != null) { response.append(line); } JSONObject jsonObj = new JSONObject(response.toString()); JSONArray jsonArray = jsonObj.getJSONArray("results"); for (int i = 0 ; i < jsonArray.length(); i++) { JSONObject characterObj = jsonArray.getJSONObject(i); // 变量移到循环内部声明,避免多线程下值覆盖 String name = characterObj.getString("name"); String height = characterObj.getString("height"); String mass = characterObj.getString("mass"); Character character1 = new Character(name,height,mass); characterArray.add(character1); // 补空格优化日志显示 Log.i("MainActivity", "The name is " + character1.name + " the height is " + character1.height); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException | JSONException e) { e.printStackTrace(); } finally { // 统一释放资源 if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null) { connection.disconnect(); } } return null; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); // 主线程通知适配器刷新 adapter.notifyDataSetChanged(); } }
补充提示:AsyncTask在Android 11及以上版本已被官方废弃,正式项目开发建议使用协程、Retrofit等更稳定的异步网络方案。
内容的提问来源于stack exchange,提问作者newbie-coder
相关产品推荐
相关产品推荐

