notifyDataSetChanged不刷新RecyclerView

8
我遇到了一个奇怪的问题。我从 ListView 切换到 RecyclerView,但是无法刷新或通知我的 ListView 发生变化。我尝试调用 Item.this.notifyDataSetChanged(); 和其他方法来刷新 View,但它不起作用。相反,当我滚动时(无论方向如何),RecyclerView 会刷新。我该如何在发生更改时通知我的 RecyclerView?
代��:
@Override
public void onBindViewHolder(Ids holder, final int position) {
    rowItemClass = (ListViewRow) rowItems.get(position);
    Log.e("swag", "OYOYOYOYOYO");
    if (Globals.isPlaying && Globals.pos == position) {

        if (pausedSamePos == true) {
            holder.pauseed_play.setVisibility(View.VISIBLE);
            holder.playing_pause.setVisibility(View.GONE);
        } else {
            holder.pauseed_play.setVisibility(View.GONE);
            holder.playing_pause.setVisibility(View.VISIBLE);
        }
        holder.song_currenttime_sb.setActive();
        holder.song_duration.setVisibility(View.INVISIBLE);
        holder.song_duration_sb.setVisibility(View.VISIBLE);
        holder.seekbar.setActive();

    } else {
        holder.seekbar.setInactive();
        holder.song_currenttime_sb.setInactive();
        holder.song_icon.setImageResource(rowItemClass.getImageId());
        holder.song_duration_sb.setVisibility(View.INVISIBLE);
        holder.song_duration.setVisibility(View.VISIBLE);
        holder.pauseed_play.setVisibility(View.GONE);
        holder.playing_pause.setVisibility(View.GONE);

    }
    sharedPreference = new SharedPreference();

    holder.song_duration.setTypeface(Globals
            .getTypefaceSecondary(context));
    holder.song_duration_sb.setTypeface(Globals
            .getTypefaceSecondary(context));
    holder.song_name.setTypeface(Globals.getTypefacePrimary(context));
    holder.song_currenttime_sb.setTypeface(Globals
            .getTypefaceSecondary(context));

    holder.song_name.setText(rowItemClass.getTitle());
    holder.song_duration.setText(rowItemClass.getDesc());

    holder.song_duration_sb.setText(rowItemClass.getDesc());
    holder.favorite.setTag(position);
    holder.song_currenttime_sb.setTag(position);
    holder.seekbar.setTag(position);
    holder.clickRegister.setTag(position);
    holder.song_icon.setTag(position);
    holder.song_name.setTag(position);
    holder.song_duration.setTag(position);
    holder.song_duration_sb.setTag(position);
    holder.more_options.setTag(position);
    // int task_id = (Integer) holder.seekbar.getTag();
    final Ids finalHolder = holder;





    holder.clickRegister.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            try {

                if ((Globals.isPlaying.booleanValue())
                        && (Globals.pos == position)) {
                    pausePlaying();

                } else {

                    Globals.stopPlaying();
                    pausedSamePos = false;
                    Globals.pos = position;
                    Globals.isPlaying = true;
                    Item.this.notifyDataSetChanged();

                    Globals.mp = MediaPlayer.create(context, Integer
                            .valueOf(Item.this.songPos[position])
                            .intValue());
                    Globals.mp.start();
                    Globals.pos = position;

                    Globals.isPlaying = Boolean.valueOf(true);
                    Item.this.notifyDataSetChanged();

                    Globals.mp
                            .setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                                @Override
                                public void onCompletion(
                                        MediaPlayer mpOnComplete) {
                                    mpOnComplete.release();

                                    Globals.isPlaying = false;
                                    pausedSamePos = false;
                                    Globals.isPlaying = Boolean
                                            .valueOf(false);
                                    finalHolder.menu_options
                                            .startAnimation(new ViewExpandAnimation(
                                                    finalHolder.menu_options));
                                    Item.this.notifyDataSetChanged();
                                }
                            });

                }
            } catch (Exception localException) {
            }

        }
    });

    holder.clickRegister
            .setOnLongClickListener(new View.OnLongClickListener() {

                @Override
                public boolean onLongClick(View v) {
                    Globals.stopPlaying();
                    Item.this.notifyDataSetChanged();
                    return true;
                }
            });




}

如果您在列表视图中使用了viewholder模式,那么在我看来,实际上使用recycler视图并没有真正的优势。 - Bhargav
它应该对动画效果更好。此外,在FragmentView中它的表现更佳。旧的ListView即使没有任何操作也会调用GetView方法,这导致性能非常差。 - Slim C.
你能发布Recycler Adapter的代码吗? - Ramesh
@Ramesh 发布了代码。 - Slim C.
什么是Item?你尝试过在Item.this.notifyDataSetChanged();的位置只使用notifyDataSetChanged();吗? - Vipul Asri
Item是类名。是的,这基本上是相同的东西。在列表滚动之前没有任何改变。 - Slim C.
4个回答

12

我一直在努力解决一个类似的问题,尝试处理这样一个使用案例:需要替换适配器的所有内容,并且recycler-view应该从头开始:调用notifyDataSetChanged()swapAdapter()以及许多后续调用视图/布局管理器无效请求的组合只会导致一个(看起来)空的 recycler-view。视图甚至没有尝试重新绑定视图持有者。

看起来已经解决了这个问题的是这个hack-ish解决方案:

view.swapAdapter(sameAdapter, true);
view.scrollBy(0, 0);

事实证明,即使使用0偏移量的scrollBy也会驱动回收视图(recycler-view)对其视图进行布局,并执行待处理视图持有者(pending view-holders)的重新绑定。


3
哎呀,老兄,你无法想象这个问题让我疯了。有时候 notifyDataSetChanged 起作用,有时候又不行,但只要我用手指轻轻地滚动一下,它就会更新。scrollBy(0, 0) 完美解决了问题,但 RecyclerView 的代码肯定有什么问题。谢谢! - Simon Ninon
你和我一样,@SimonNinon :-) 很高兴能帮忙! - d4vidi
2
感谢您的回答,顺便提一下为什么这个方法可行 - 它调用了RecyclerView.consumePendingUpdateOperations()以执行挂起的更新。 - Hai Zhang

2
如果你想通知你的RecycleListView更新,只需要在你的适配器类中简单地调用notifyDataSetChanged()方法。下面是我适配器类中的方法:
public class ListAdapter extends RecyclerView.Adapter<Listdapter.ViewHolder> {
....
private List<DesaObject> desaObjects= new ArrayList<DesaObject>();

public void setListObjects(List<DesaObject> desaObjects){
        if(this.desaObjects.size()>0)
            this.desaObjects.clear();
        this.desaObjects = desaObjects;
        notifyDataSetChanged();
    }
....

public static class ViewHolder extends RecyclerView.ViewHolder {
       public final View mView;
       public final AppCompatTextView desa;


       public ViewHolder(View view) {
           super(view);
           mView = view;
           desa = (AppCompatTextView) view.findViewById(R.id.desa);
       }

   }
}

在你的代码中,你实际上没有在OnClickListener中设置或更改你的listObjects,请尝试使用notifyDataSetChanged()而不是Item.this.notifyDataSetChanged();


我设置了一些对象的状态,有些对象被初始化以更新(文本/滑动条),其他对象被设置为可见,所有这些都有效,除了更新部分。SeekBar和TextView在视图滚动之前不会更新(它们被更新了,但进度未显示)。而改变为“notifyDataSetChanged();”也没有改变任何东西。 - Slim C.

2

我不确定为什么会这样,但是notifyDataSetChanged();没有起作用。所以我尝试手动跟踪更改的项目,并使用notifyItemChanged(int);手动刷新它们,到目前为止似乎可以工作。我仍然不确定为什么刷新整个RecyclerView没有起作用。


1

使用更改后的数据重新初始化您的适配器,并使用方法'swapadapter'。希望能够帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接