How to update RecyclerView Adapter Data
I'm working with RecyclerView and both the remove and the update work well.
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.
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
Strange Outofmemory Issue While Loading an Image to a Bitmap Object
How to Lazy Load Images in Listview in Android
How to Save an Activity State Using the Save Instance State
Remove Apk from Library in Google Play Developer Console
Android: How to Open a Specific Folder Via Intent and Show Its Content in a File Browser
How to Set Up Android Studio to Work Completely Offline
Difference Between Px, Dip, Dp, and Sp
How to Close/Hide the Android Soft Keyboard Programmatically
How to Unlock Android Phone Through Adb
How to Place an Imageview on Top of Another Imageview in Android
How to Remove Android Auto-Suggest Underlining in Edittext
Android 8: Cleartext Http Traffic Not Permitted
How to Programmatically Take a Screenshot on Android
How to Enable Front Camera Instead of Rear Camera for Android Programmatically