Android Studio基于OkHttp实现API对接ListView功能求助
代码问题汇总
- API类构造函数未给成员变量
teamName赋值,传入的查询参数没有被拼接到请求URL中,接口拿不到查询关键词。 - 异步逻辑嵌套错误:同时使用
AsyncTask和OkHttp异步enqueue方法,doInBackground方法会在OkHttp请求返回前就执行结束,调用getTeamsInfo()永远只能拿到空列表。 - Gson解析逻辑错误:现有
Data类仅对应单条球队数据,未匹配接口返回的外层JSON结构,且代码中存在未定义的lst类、TAG常量、Data()方法,无法通过编译。 - 线程使用违规:OkHttp回调运行在子线程,直接在回调中执行Toast弹出、ListView更新等UI操作会触发安卓线程异常,所有UI操作必须切换到主线程执行。
- 冗余代码过多:导入了大量未使用的类,增加编译负担。
修正实现方案
第一步:调整实体类结构
删掉原Data类中冗余的手动解析方法,新增外层响应包装类匹配API返回结构:
// 单条球队数据实体,建议重命名为Team语义更清晰 import com.google.gson.annotations.SerializedName; public class Team { @SerializedName("team") private String team; @SerializedName("played") private String played; @SerializedName("win") private String win; @SerializedName("draw") private String draw; @SerializedName("loss") private String loss; @SerializedName("goalsFor") private String goalsFor; @SerializedName("goalsAgainst") private String goalsAgainst; @SerializedName("points") private String points; public String getTeam() {return team;} public String getPlayed() {return played;} public String getWin() {return win;} public String getDraw() {return draw;} public String getLoss() {return loss;} public String getGoalsFor() {return goalsFor;} public String getGoalsAgainst() {return goalsAgainst;} public String getPoints() {return points;} } // 外层API响应包装类,匹配接口返回的JSON结构 public class ApiResponse { @SerializedName("teams") private List<Team> teams; public List<Team> getTeams() {return teams;} }
第二步:重构页面请求逻辑
删掉冗余的AsyncTask嵌套,直接使用OkHttp发起异步请求,请求完成后切主线程更新列表:
package com.example.myapplication; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.SearchView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.gson.Gson; import java.io.IOException; import java.util.ArrayList; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class TopScorer extends AppCompatActivity { private SearchView searchView; private ListView listView; private ArrayAdapter<String> arrayAdapter; private ArrayList<String> displayList = new ArrayList<>(); private final OkHttpClient client = new OkHttpClient(); private static final String API_KEY = "6ad8dfcfcbmshb4a45a22532e4a1p1efecajsnc2fb433de0da"; private static final String API_HOST = "heisenbug-premier-league-live-scores-v1.p.rapidapi.com"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_top_scorer); searchView = findViewById(R.id.search); listView = findViewById(R.id.listview); // 适配器仅初始化一次 arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, displayList); listView.setAdapter(arrayAdapter); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { fetchTeamData(query.trim()); return true; } @Override public boolean onQueryTextChange(String newText) { return false; } }); } private void fetchTeamData(String teamName) { String requestUrl = "https://heisenbug-premier-league-live-scores-v1.p.rapidapi.com/api/premierleague/team?name=" + teamName; Request request = new Request.Builder() .url(requestUrl) .get() .addHeader("X-RapidAPI-Key", API_KEY) .addHeader("X-RapidAPI-Host", API_HOST) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { runOnUiThread(() -> Toast.makeText(TopScorer.this, "请求失败,请检查网络", Toast.LENGTH_SHORT).show()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (!response.isSuccessful()) { runOnUiThread(() -> Toast.makeText(TopScorer.this, "请求异常,错误码:" + response.code(), Toast.LENGTH_SHORT).show()); return; } String responseStr = response.body().string(); Gson gson = new Gson(); ApiResponse apiResponse = gson.fromJson(responseStr, ApiResponse.class); displayList.clear(); int index = 1; if (apiResponse.getTeams() != null) { for (Team team : apiResponse.getTeams()) { displayList.add(index + ". 球队:" + team.getTeam()); displayList.add("出场次数:" + team.getPlayed()); displayList.add("胜场:" + team.getWin()); displayList.add("平场:" + team.getDraw()); displayList.add("负场:" + team.getLoss()); displayList.add("进球数:" + team.getGoalsFor()); displayList.add("失球数:" + team.getGoalsAgainst()); displayList.add("积分:" + team.getPoints()); displayList.add(""); index++; } } // 切主线程刷新UI runOnUiThread(() -> { if (displayList.isEmpty()) { Toast.makeText(TopScorer.this, "未查询到对应球队数据", Toast.LENGTH_SHORT).show(); } arrayAdapter.notifyDataSetChanged(); }); } }); } }
配置注意事项
- 确认
AndroidManifest.xml中已添加网络权限:<uses-permission android:name="android.permission.INTERNET" /> - 本次调用的接口为HTTPS协议,无需额外配置Android 9+的明文网络访问规则。
- 不要重复创建ArrayAdapter实例,初始化一次后仅更新数据源、调用
notifyDataSetChanged()刷新即可,减少性能损耗。
内容的提问来源于stack exchange,提问作者Brie
相关产品推荐
相关产品推荐

