Android ListView滑动到第6/7项后重复显示首项,求问题成因及解决方法
问题根因
getItemId实现错误:所有项固定返回0,导致ListView无法正确区分不同列表项,复用逻辑混乱。无特殊业务要求时,该方法直接返回对应位置参数即可。getView复用逻辑完全错误(核心原因):
每次进入getView都会新建ViewHolder并新Inflate布局,但当系统传入已经回收的复用View(convertView!=null)时,你直接返回了这个旧View,你给新ViewHolder设置的数据完全没有绑定到要返回的旧View上,所以旧View会保留之前渲染的内容,也就是滑出屏幕的第一条内容,就出现了重复展示的问题。同时你没有使用setTag/getTag缓存ViewHolder,完全没有起到复用优化的作用。- 附加问题:全局仅持有一个MediaPlayer实例,点击不同列表项的播放按钮会出现逻辑冲突,不符合音乐列表的交互需求。
修复代码示例
// 修复getItemId @Override public long getItemId(int i) { return i; } static class ViewHolder{ TextView textView_songName,textView_artist; ImageView imageView_play,imageView_stop; } @Override public View getView(int i, View convertView, ViewGroup parent) { ViewHolder viewholder; // 只有convertView为空的时候才新建布局和ViewHolder if (convertView == null) { viewholder = new ViewHolder(); LayoutInflater layoutInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(layout, parent, false); // 绑定控件到ViewHolder viewholder.textView_songName = convertView.findViewById(R.id.textView_song); viewholder.textView_artist = convertView.findViewById(R.id.textView_artist); viewholder.imageView_play = convertView.findViewById(R.id.image_play); viewholder.imageView_stop = convertView.findViewById(R.id.image_stop); // ViewHolder缓存到convertView的tag里 convertView.setTag(viewholder); } else { // 复用的时候直接从tag取ViewHolder viewholder = (ViewHolder) convertView.getTag(); } final Music music = myList.get(i); // 给当前ViewHolder的控件设置数据 viewholder.textView_songName.setText(music.getSongName()); viewholder.textView_artist.setText(music.getArtist()); // 点击事件逻辑建议结合业务优化MediaPlayer的管理,这里仅保留原有逻辑 viewholder.imageView_play.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (flag) { medialayer = MediaPlayer.create(context, music.getSongs()); flag = false; } if (medialayer.isPlaying()) { medialayer.pause(); viewholder.imageView_play.setImageResource(R.drawable.ic_play); } else { medialayer.start(); viewholder.imageView_play.setImageResource(R.drawable.ic_pause); } } }); viewholder.imageView_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!flag) { medialayer.stop(); medialayer.release(); flag = true; } viewholder.imageView_stop.setImageResource(R.drawable.ic_stop); viewholder.imageView_play.setImageResource(R.drawable.ic_play); } }); return convertView; }
内容的提问来源于stack exchange,提问作者Hitesh Shimpi
相关产品推荐
相关产品推荐

