Android Studio中Fragment调用REST API后ListView无内容展示问题求助
问题排查及修复方案
核心问题1:异步请求完成后未通知列表刷新
Volley的网络请求是异步执行的,你在onViewCreated中调用getEvents()之后立刻初始化并绑定了适配器,此时matches列表是空的。等网络请求回调onResponse中往matches里新增数据后,适配器感知不到数据变化,不会重新渲染列表。
修复方法:把适配器提升为Fragment的全局变量,在onResponse中添加完数据后调用adapter.notifyDataSetChanged()刷新列表。
核心问题2:ArrayAdapter构造函数传参错误
你自定义的MatchesAdapter继承自ArrayAdapter,但构造函数调用super(context, matches_layout)时没有传入数据源,ArrayAdapter内部默认的item数量为0,就算你本地持有了matchList也不会生效。
修复方法:修改构造函数的super调用,传入数据源:
public MatchesAdapter(Context context, int matches_layout, ArrayList<Matches> matches) { super(context, matches_layout, matches); // 新增第三个参数传入数据源 this.matchList = matches; }
潜在问题:int类型的比分直接setText会崩溃
你的setResultHome/setResultAway传入的是int类型数值,调用setText()的时候如果直接传入int,系统会把这个数值当成字符串资源ID去查找,找不到就会抛异常崩溃。
修复方法:把int转成字符串再设置:
home_result.setText(String.valueOf(matchList.get(position).getResultHome())); away_result.setText(String.valueOf(matchList.get(position).getResultAway()));
完整修改后的代码示例
1. Calendar Fragment修改:
public class Calendar extends Fragment { private static final String baseUrl = "https://xxx"; private static final String events = "/wp-json/sportspress/v2/events"; EventsJsonObjectToMatchesConverter converter; ArrayList<Matches> matches = new ArrayList<>(); MatchesAdapter adapter; // 提升为全局变量 @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.calendar_layout,container, false); return rootView; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ListView lv = (ListView)view.findViewById(R.id.matches); adapter = new MatchesAdapter(this.getContext(), R.layout.matches_layout, matches); lv.setAdapter(adapter); this.getEvents(); // 先设适配器再发请求不影响逻辑 } private void getEvents() { RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext()); String url =getString(R.string.baseUrl) + getString(R.string.eventsEndpoit); StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { Matches match = new Matches(); match.setHomeTeam("simone"); match.setAwayTeam("gaspa"); match.setResultHome(2); match.setResultAway(1); match.setDate("05/10/2021 - 10:00"); matches.add(match); adapter.notifyDataSetChanged(); // 通知适配器刷新列表 System.out.println(matches.size()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // 建议新增错误提示逻辑,方便后续排查问题 } }){ @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> params = new HashMap<String, String>(); params.put("Content-Type", "application/json; charset=UTF-8"); params.put( "Authorization", String.format("Basic %s", Base64.encodeToString( String.format("%s:%s", getString(R.string.user), getString(R.string.password)).getBytes(), Base64.DEFAULT))); return params; } }; queue.add(stringRequest); } }
2. MatchesAdapter修改:
public class MatchesAdapter extends ArrayAdapter<Matches> { private ArrayList<Matches> matchList; public MatchesAdapter(Context context, int matches_layout, ArrayList<Matches> matches) { super(context, matches_layout, matches); // 修复构造函数传参 this.matchList = matches; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { if(convertView == null){ convertView = LayoutInflater.from(getContext()).inflate(R.layout.matches_layout,parent, false); } TextView home = convertView.findViewById(R.id.squadra_casa); TextView away = convertView.findViewById(R.id.squadra_trasferta); TextView home_result = convertView.findViewById(R.id.risultato_casa); TextView away_result = convertView.findViewById(R.id.risultato_trasferta); TextView group = convertView.findViewById(R.id.girone); TextView date = convertView.findViewById(R.id.data_ora); home.setText(matchList.get(position).getHomeTeam()); away.setText(matchList.get(position).getAwayTeam()); home_result.setText(String.valueOf(matchList.get(position).getResultHome())); // 数值转字符串避免崩溃 away_result.setText(String.valueOf(matchList.get(position).getResultAway())); // 数值转字符串避免崩溃 // 注意如果group字段没有赋值,这里设置会显示空值,无对应字段可以注释此行或者设置默认值 // group.setText(matchList.get(position).getGroup()); date.setText(matchList.get(position).getDate()); return convertView; } }
内容的提问来源于stack exchange,提问作者user3484121
相关产品推荐
相关产品推荐

