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

Android Java页面OkHttp获取JSON成功但ListView不显示数据

问题根因

列表空白核心是网络请求时序逻辑写错了:

  • 你在AsyncTask的doInBackground里调用OkHttp的enqueue发异步请求,这个方法是非阻塞的,请求会丢给OkHttp自己的线程池执行,doInBackground会立刻执行return null,马上触发onPostExecute。
  • 这时候OkHttp的响应还没回来,resultList是空的,你把空集合传给SimpleAdapter绑定ListView,当然显示空白。等后续回调把数据塞进resultList的时候,Adapter早就初始化完成了,感知不到数据变化,不会刷新界面。

另外还有几个隐患:

  • 子线程直接修改resultList没有加同步,存在并发修改风险
  • 重复导入java.util.ArrayList,还有Gson、SearchView、ArrayAdapter等一堆没用到的冗余导入,虽然不影响运行但没必要留
  • OkHttp回调本身在子线程,就算数据加载完你直接更新UI也会崩溃,必须切主线程
修复方案

两种改法二选一,不要混着写多套异步逻辑:

方案1:OkHttp改同步调用,适配现有AsyncTask逻辑

去掉enqueue异步回调,直接用OkHttp同步方法execute(),在doInBackground里直接完成响应读取、JSON解析,等所有数据处理完再返回,这样onPostExecute执行的时候resultList里已经有完整数据了。

doInBackground修改后核心代码:

@Override
protected Void doInBackground(Void... arg0) {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url("https://heisenbug-premier-league-live-scores-v1.p.rapidapi.com/api/premierleague/team?name=Liverpool")
            .get()
            .addHeader("X-RapidAPI-Key", "替换成你自己的有效Key")
            .addHeader("X-RapidAPI-Host", "heisenbug-premier-league-live-scores-v1.p.rapidapi.com")
            .build();
    try {
        Response response = client.newCall(request).execute();
        if (!response.isSuccessful()) return null;
        String jsonStr = response.body().string();
        Log.e(TAG, "Response from url: " + jsonStr);
        if (jsonStr == null) return null;
        JSONObject jsonObj = new JSONObject(jsonStr);
        JSONArray records = jsonObj.getJSONArray("records");
        for (int i = 0; i < records.length(); i++) {
            JSONObject c = records.getJSONObject(i);
            HashMap<String, String> result = new HashMap<>();
            result.put("league",c.getString("league"));
            result.put("season",c.getString("season"));
            result.put("name",c.getString("name"));
            result.put("officialName",c.getString("officialName"));
            result.put("address",c.getString("address"));
            result.put("telephone",c.getString("telephone"));
            result.put("fax",c.getString("fax"));
            result.put("website",c.getString("website"));
            result.put("founded",c.getString("founded"));
            result.put("teamSize",c.getString("teamSize"));
            result.put("averageAge",c.getString("averageAge"));
            result.put("foreigners",c.getString("foreigners"));
            result.put("nationaTeamPlayers",c.getString("nationaTeamPlayers"));
            result.put("teamValue",c.getString("teamValue"));
            result.put("venue",c.getString("venue"));
            result.put("venueCapacity",c.getString("venueCapacity"));
            resultList.add(result);
        }
    } catch (IOException | JSONException e) {
        Log.e(TAG, "加载失败: " + e.getMessage());
        runOnUiThread(() -> Toast.makeText(getApplicationContext(),
                "数据加载失败: " + e.getMessage(), Toast.LENGTH_LONG).show());
    }
    return null;
}

方案2:删掉多余的AsyncTask,直接用OkHttp异步回调处理

AsyncTask本身在高版本Android已经被废弃,完全没必要多包一层。直接在onCreate里发起OkHttp异步请求,等回调里解析完所有数据,再切到主线程给ListView绑定Adapter即可。

核心逻辑示例:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_team_info);
    resultList = new ArrayList<>();
    lv = findViewById(R.id.list);
    Toast.makeText(this,"Json Data is downloading",Toast.LENGTH_LONG).show();

    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url("https://heisenbug-premier-league-live-scores-v1.p.rapidapi.com/api/premierleague/team?name=Liverpool")
            .get()
            .addHeader("X-RapidAPI-Key", "替换成你自己的有效Key")
            .addHeader("X-RapidAPI-Host", "heisenbug-premier-league-live-scores-v1.p.rapidapi.com")
            .build();
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) {
            runOnUiThread(() -> Toast.makeText(TeamInfo.this, "网络请求失败", Toast.LENGTH_LONG).show());
        }

        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
            String jsonStr = response.body().string();
            Log.e(TAG, "Response from url: " + jsonStr);
            if (jsonStr != null) {
                try {
                    JSONObject jsonObj = new JSONObject(jsonStr);
                    JSONArray records = jsonObj.getJSONArray("records");
                    for (int i = 0; i < records.length(); i++) {
                        JSONObject c = records.getJSONObject(i);
                        HashMap<String, String> result = new HashMap<>();
                        result.put("league",c.getString("league"));
                        result.put("season",c.getString("season"));
                        result.put("name",c.getString("name"));
                        result.put("officialName",c.getString("officialName"));
                        result.put("address",c.getString("address"));
                        result.put("telephone",c.getString("telephone"));
                        result.put("fax",c.getString("fax"));
                        result.put("website",c.getString("website"));
                        result.put("founded",c.getString("founded"));
                        result.put("teamSize",c.getString("teamSize"));
                        result.put("averageAge",c.getString("averageAge"));
                        result.put("foreigners",c.getString("foreigners"));
                        result.put("nationaTeamPlayers",c.getString("nationaTeamPlayers"));
                        result.put("teamValue",c.getString("teamValue"));
                        result.put("venue",c.getString("venue"));
                        result.put("venueCapacity",c.getString("venueCapacity"));
                        resultList.add(result);
                    }
                    // 切主线程绑定Adapter
                    runOnUiThread(() -> {
                        ListAdapter adapter = new SimpleAdapter(TeamInfo.this, resultList,
                                R.layout.list_item_team, new String[]{ "league","season","name","officialName","address","telephone","fax","website","founded","teamSize","averageAge","foreigners","nationaTeamPlayers","teamValue","venue","venueCapacity"},
                                new int[]{R.id.league, R.id.season,R.id.name,R.id.officialName,R.id.address,R.id.telephone,R.id.fax,R.id.website,R.id.founded,R.id.teamSize,R.id.averageAge,R.id.foreigners,R.id.nationaTeamPlayers,R.id.teamValue,R.id.venue,R.id.venueCapacity});
                        lv.setAdapter(adapter);
                    });
                } catch (final JSONException e) {
                    Log.e(TAG, "Json parsing error: " + e.getMessage());
                    runOnUiThread(() -> Toast.makeText(getApplicationContext(),
                            "Json parsing error: " + e.getMessage(), Toast.LENGTH_LONG).show());
                }
            }else {
                Log.e(TAG, "Couldn't get json from server.");
                runOnUiThread(() -> Toast.makeText(getApplicationContext(),
                        "Couldn't get json from server. Check LogCat for possible errors!",
                        Toast.LENGTH_LONG).show());
            }
        }
    });
}
额外检查项
  • 确认AndroidManifest.xml里已经加了网络权限:<uses-permission android:name="android.permission.INTERNET" />,否则高版本系统会直接拦截网络请求
  • 所有UI相关操作(弹Toast、绑定Adapter、更新View)必须在主线程执行,OkHttp的回调默认在子线程,必须用runOnUiThread切换
  • 删掉没用的冗余导入,避免不必要的编译警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:27:04