9

I have a weird problem. I switched to RecyclerView from ListView and I can't refresh or notify of change in my ListView. I tried calling Item.this.notifyDataSetChanged(); and other methods to refresh View but it doesn't work. Instead RecyclerView is refreshed when I scroll(regardless of direction). How can I notify my RecyclerView when there is a change?

CODE:

@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; } }); } 
6
  • if you are using viewholder pattern in your list views there is actually no real advantage in using recycler views imo Commented Dec 5, 2015 at 12:27
  • Well It's supposed to be better for animations. Besides it does work better in FragmentView. Old ListView was calling GetView method even when nothing was happening and that resulted in very poor performance. Commented Dec 5, 2015 at 12:28
  • can you post recycler adapter code Commented Dec 5, 2015 at 12:32
  • @Ramesh Code posted. Commented Dec 5, 2015 at 12:37
  • what is Item? Have you tried using only notifyDataSetChanged(); in place of Item.this.notifyDataSetChanged();. Commented Dec 5, 2015 at 13:06

4 Answers 4

13

I've been struggling hard with a similar issue, trying to handle a use-case where all of the adapter's content has to be replaced and the recycler-view should start from scratch: calling notifyDataSetChanged(), swapAdapter() with numerous combinations of subsequent calls to view/layout-manager invalidation requests resulted in nothing but a (seemingly) empty recycler-view. The view didn't even try to rebind the view holders.

What seemed to have worked it out is this hack-ish fix:

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

As it turns out, scrollBy (even with 0 offsets) drives the recycler-view into laying out its views and executing the pending view-holders rebinding.

Sign up to request clarification or add additional context in comments.

3 Comments

oh damn dude, you can't imagine how this problem was driving me crazy. Randomly, notifyDataSetChanged worked, and sometimes it didn't, but as soon as I scrolled a bit with my fingers, it got updated. .scrollBy(0, 0) does perfectly the trick, but there is definitely something wrong in the RecyclerView code. Thaanks!
You and me both, @SimonNinon :-) Happy to help!
Thanks for this answer, and a side note on why this works - it calls RecyclerView.consumePendingUpdateOperations() so that pending updates are executed.
2

if you want notify your recycleListView just simple call notifyDataSetChanged(); in your class adapter. this is my method in my adapter class :

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); } } } 

in your code you dont actually set or change your listObjects in the OnClickListener and please try notifyDataSetChanged(); instead of Item.this.notifyDataSetChanged();

1 Comment

Well I do set state of some objects, some objects are initialized to update(text/seekbar)other objects are set visible, all that works, except for the updating part. SeekBar and TextView are not updated until view is scrolled(they are updated but progress is not displayed) And changing to notifyDataSetChanged(); changes nothing.
2

I am not sure why is this, but notifyDataSetChanged(); didn't work. So I tried keeping track of changed items and refreshing them manually with notifyItemChanged(int); and so far it seems to be working. I am still not sure why refreshing whole RecyclerView didn't work.

Comments

1

Initialize your Adapter Again with changed data and use method 'swapadapter'. hope it helps.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.