Reload Recyclerview from Within the Adapter of the Recycler View

How to update RecyclerView Adapter Data

I'm working with RecyclerView and both the remove and the update work well.

  1. Remove:

    There are four steps to remove an item from a RecyclerView

     list.remove(position);
    recycler.removeViewAt(position);
    mAdapter.notifyItemRemoved(position);
    mAdapter.notifyItemRangeChanged(position, list.size());

    These lines of code work for me.

  2. Update the data:

    The only things I had to do was:

     mAdapter.notifyDataSetChanged();

You had to do all of this in the Actvity/Fragment code, not in the RecyclerView Adapter code.

Reload recyclerview from within the adapter of the recycler view

In the method:

public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)

Change this

   return new HeaderViewHolder(itemView, ctx);

To this:

  return new HeaderViewHolder(itemView, ctx, this);

in HeadeViewHolder Contstructor change to this:

public HeaderViewHolder(View itemView, Context ctx, Profile_RecyclerViewAdapter adapter) : base(itemView)

Then in the click listener call this.

adapter.notifyDataSetChanged();

How to refresh recyclerView after changing data?

Change this:

holder.cardView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
listener.onLongClicked(alarm);
return true;
}
});

To this:

holder.cardView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
listener.onLongClicked(alarm);
alarms.remove(holder.getAdapterPosition()); //or alarms.remove(alarm);
notifyItemRemoved(holder.getAdapterPosition()); //or notifyDataSetChanged();
return true;
}
});

The problem is that you're removing the alarm from your database when you call removeAlarm() in your Activity, but you're not actually removing it from the alarms list in your Adapter. The change isn't being reflected because the data set never changes in your code. When you recreate your Activity, you pass the new database list into the Adapter, so it updates then.

I also recommend not doing this:

public void getData(){
new Thread(new Runnable() {
@Override
public void run() {
for (Alarm alarm : alarmDao.getAll()){
alarmsList.add(alarm);
}
}
}).start();
}

While alarmsList in your Activity and alarms are the same instance, and thus reflect the same additions and removals, there's no guarantee this logic will complete before the RecyclerView is inflated and the adapter attached. That means you could end up with missing data, especially on slower devices.

Unless you have an absolute ton of Alarms, there's no need to run that in a new Thread. You could just move that for-loop right above where you initialize the Adapter, and use the addAll() method:

alarmsList.addAll(alarmDuo.getAll());
mAdapter = //your assignment from your code

If you do need it to be async, attach the Adapter later, inside your Thread:

public void getData(){
new Thread(new Runnable() {
@Override
public void run() {
alarmsList.addAll(alarmDuo.getAll());
runOnUiThread(new Runnable() {
mAdapter = new AlarmRecyclerAdapter(alarmsList, recyclerListener);
recyclerView.setAdapter(mAdapter);
}
}
}).start();
}

Remove the assignment, adapter setting and notifyDataSetChanged() calls from your onCreate() method:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarms_activity);
db = App.getInstance().getDataBase();
alarmDao = db.AlarmDao();
recyclerView = findViewById(R.id.recycler);
recyclerListener = new OnClickedRecyclerAdapter<Alarm>() {
@Override
public void onLongClicked(final Alarm data) {
removeAlarm(data);
}

@Override
public void onClicked(Alarm data) {

}
};
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
getData();

}

refresh the whole RecyclerView from within the Adapter

Call below method to refresh inside adapter:

notifyDataSetChanged()

Inside activity

if (recyclerView.getAdapter() != null) {
recyclerView.getAdapter().notifyDataSetChanged();
}

RecyclerView: how to refresh data

It seems that my problem was that I supposed that I needed to keep an internal private variable, synchronized with the real external data to be shown. I was wrong: the Adapter must be directly linked to the data that must be shown, through a reference. The private copy is just a private reference to the public data, so copying the addressed data in the constructor is wrong.
At that point, if the constructor of the Adapter is fed with the reference to some data object, it can be notified at every change with notifyDataSetChanged() .

How do I update recyclerView inside onBindViewHolder of its adapter?

You need to update your existing variable

String[] strings;

And then tell the RecyclerView to redraw the items.

notifyItemRemoved(position);

or

notifyDataSetChanged();

You then get

case DialogInterface.BUTTON_POSITIVE:
dbManager = new DBManager(holder.itemView.getContext(),null,null,1);
dbManager.deleteList(strings[position]);
strings = dbManager.showLists();
notifyItemRemoved(position);
break;


Related Topics



Leave a reply



Submit