CustomAdapter的getCount()先返回正数后立即返回0致ListView为空
我帮你找出了几个导致ListView无内容、getCount()异常的核心问题,以及对应的修复方案:
核心问题分析
ArrayAdapter内部数据集与自定义变量不同步
你继承了ArrayAdapter,但自己维护了一个rows列表,却没和ArrayAdapter内部的数据集同步。ArrayAdapter的getCount()是基于自身内部的mObjects列表计算的,不是你自定义的rows变量——这就是为什么一开始构造函数里能看到100条数据,之后却返回0的原因。无效的提前绑定Adapter
在onCreate里你直接调用了list.setAdapter(customAdapter),但此时customAdapter还是null,这完全是无效操作,还可能干扰后续的Adapter绑定逻辑。冗余的数据集重复设置
在parseHtml里创建完CustomAdapter后,又调用setData(rows)传递同一个列表,不仅多余,还可能导致数据集混乱。
修复方案
1. 修正CustomAdapter,同步数据集
删除自定义的rows变量,直接利用ArrayAdapter的内置方法管理数据,确保getCount()始终返回正确的数据集大小:
package com.example.topsongsbyyear; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import java.util.ArrayList; public class CustomAdapter extends ArrayAdapter<RowItem> { Context context; public CustomAdapter(Context context, int resource, ArrayList<RowItem> rows) { super(context, resource, rows); this.context = context; Log.i("--------------", "Adapter初始化,数据条数:" + getCount()); } // 正确的更新数据方法:同步ArrayAdapter内部数据集 public void setData(ArrayList<RowItem> newRows) { clear(); // 清空旧数据 addAll(newRows); // 添加新数据 notifyDataSetChanged(); // 通知ListView刷新 Log.i("--------------", "数据更新完成,当前条数:" + getCount()); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.row_layout, parent, false); } // 绑定控件 TextView rank = convertView.findViewById(R.id.rank); TextView songName = convertView.findViewById(R.id.song_name); TextView artist = convertView.findViewById(R.id.artist); ImageView image = convertView.findViewById(R.id.song_image); // 获取当前项数据 RowItem item = getItem(position); if (item != null) { rank.setText(item.getRank()); songName.setText(item.getSongName()); artist.setText(item.getArtist()); Glide.with(context).load(item.getImageUrl()).into(image); } return convertView; } }
2. 修正SongList Activity的逻辑
移除无效的提前绑定,优化Adapter的创建与更新逻辑:
package com.example.topsongsbyyear; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.ListView; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.util.ArrayList; public class SongList extends AppCompatActivity implements Response.ErrorListener, Response.Listener<String> { String webUrl; String year; RequestQueue requestQueue; StringRequest stringRequest; ListView list; ArrayList<RowItem> rows; CustomAdapter customAdapter; // 直接声明为CustomAdapter,方便调用方法 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); year = getIntent().getStringExtra("year"); webUrl = "https://www.billboard.com/charts/year-end/" + year + "/hot-100-songs"; setContentView(R.layout.activity_song_list); rows = new ArrayList<>(); list = findViewById(R.id.all_list); requestQueue = Volley.newRequestQueue(this); stringRequest = new StringRequest(Request.Method.GET, webUrl, this, this); requestQueue.add(stringRequest); // 不需要调用requestQueue.start(),Volley添加请求后会自动处理 } @Override public void onErrorResponse(VolleyError error) { Log.i("----------------", "请求失败:" + error.getMessage()); } @Override public void onResponse(String response){ Log.i("----------------", "请求成功,开始解析HTML"); Document doc = Jsoup.parse(response); parseHtml(doc); } public void parseHtml(Document doc){ ArrayList<String> songList = new ArrayList<>(); ArrayList<String> artistList = new ArrayList<>(); ArrayList<String> imageUrls = new ArrayList<>(); rows = new ArrayList<>(); // 解析HTML内容 Elements songs = doc.select(".ye-chart-item__title"); for(Element song : songs){ songList.add(song.text().trim()); } Elements artists = doc.select(".ye-chart-item__artist"); for(Element artist : artists){ artistList.add(artist.text().trim()); } Elements images = doc.select("div.ye-chart-item__image > img"); for (Element image : images) { imageUrls.add(image.attr("src")); } // 填充RowItem列表 int maxCount = Math.min(Math.min(songList.size(), artistList.size()), imageUrls.size()); for(int i = 0; i < maxCount; i++){ rows.add(new RowItem(Integer.toString(i+1), songList.get(i), artistList.get(i), imageUrls.get(i))); } Log.i("----------------", "解析完成,数据条数:" + rows.size()); // 更新Adapter:存在则更新数据,不存在则创建并绑定 if (customAdapter == null) { customAdapter = new CustomAdapter(this, R.layout.row_layout, rows); list.setAdapter(customAdapter); } else { customAdapter.setData(rows); } } }
额外注意事项
- 确保
RowItem类的getter方法(getRank()、getSongName()等)正确实现,否则getView中无法获取数据。 - 网页结构可能会变化,要定期检查Jsoup的选择器是否还能匹配目标元素。
- 可以添加异常处理,避免解析HTML时因列表长度不一致导致崩溃(比如上面代码中用
Math.min取最小长度)。
内容的提问来源于stack exchange,提问作者Luke Lewis
相关产品推荐
相关产品推荐

