Trying to figure out what is the issue with updating RecyclerView
\'s Adapter.
After I get a new List of products, I tried to:
Update t
This is a general answer for future visitors. The various ways to update the adapter data are explained. The process includes two main steps every time:
Add "Pig" at index 2
.
String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);
Insert three more animals at index 2
.
ArrayList<String> items = new ArrayList<>();
items.add("Pig");
items.add("Chicken");
items.add("Dog");
int insertIndex = 2;
data.addAll(insertIndex, items);
adapter.notifyItemRangeInserted(insertIndex, items.size());
Remove "Pig" from the list.
int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
Remove "Camel" and "Sheep" from the list.
int startIndex = 2; // inclusive
int endIndex = 4; // exclusive
int count = endIndex - startIndex; // 2 items will be removed
data.subList(startIndex, endIndex).clear();
adapter.notifyItemRangeRemoved(startIndex, count);
Clear the whole list.
data.clear();
adapter.notifyDataSetChanged();
Clear the old list then add a new one.
// clear old list
data.clear();
// add new list
ArrayList<String> newList = new ArrayList<>();
newList.add("Lion");
newList.add("Wolf");
newList.add("Bear");
data.addAll(newList);
// notify adapter
adapter.notifyDataSetChanged();
The adapter
has a reference to data
, so it is important that I didn't set data
to a new object. Instead I cleared the old items from data
and then added the new ones.
Change the "Sheep" item so that it says "I like sheep."
String newValue = "I like sheep.";
int updateIndex = 3;
data.set(updateIndex, newValue);
adapter.notifyItemChanged(updateIndex);
Move "Sheep" from position 3
to position 1
.
int fromPosition = 3;
int toPosition = 1;
// update data array
String item = data.get(fromPosition);
data.remove(fromPosition);
data.add(toPosition, item);
// notify adapter
adapter.notifyItemMoved(fromPosition, toPosition);
Here is the project code for your reference. The RecyclerView Adapter code can be found at this answer.
MainActivity.java
public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {
List<String> data;
MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data to populate the RecyclerView with
data = new ArrayList<>();
data.add("Horse");
data.add("Cow");
data.add("Camel");
data.add("Sheep");
data.add("Goat");
// set up the RecyclerView
RecyclerView recyclerView = findViewById(R.id.rvAnimals);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
layoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
adapter = new MyRecyclerViewAdapter(this, data);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
}
@Override
public void onItemClick(View view, int position) {
Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
}
public void onButtonClick(View view) {
insertSingleItem();
}
private void insertSingleItem() {
String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);
}
private void insertMultipleItems() {
ArrayList<String> items = new ArrayList<>();
items.add("Pig");
items.add("Chicken");
items.add("Dog");
int insertIndex = 2;
data.addAll(insertIndex, items);
adapter.notifyItemRangeInserted(insertIndex, items.size());
}
private void removeSingleItem() {
int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
}
private void removeMultipleItems() {
int startIndex = 2; // inclusive
int endIndex = 4; // exclusive
int count = endIndex - startIndex; // 2 items will be removed
data.subList(startIndex, endIndex).clear();
adapter.notifyItemRangeRemoved(startIndex, count);
}
private void removeAllItems() {
data.clear();
adapter.notifyDataSetChanged();
}
private void replaceOldListWithNewList() {
// clear old list
data.clear();
// add new list
ArrayList<String> newList = new ArrayList<>();
newList.add("Lion");
newList.add("Wolf");
newList.add("Bear");
data.addAll(newList);
// notify adapter
adapter.notifyDataSetChanged();
}
private void updateSingleItem() {
String newValue = "I like sheep.";
int updateIndex = 3;
data.set(updateIndex, newValue);
adapter.notifyItemChanged(updateIndex);
}
private void moveSingleItem() {
int fromPosition = 3;
int toPosition = 1;
// update data array
String item = data.get(fromPosition);
data.remove(fromPosition);
data.add(toPosition, item);
// notify adapter
adapter.notifyItemMoved(fromPosition, toPosition);
}
}
notifyDataSetChanged()
, then no animation will be performed. This can also be an expensive operation, so it is not recommended to use notifyDataSetChanged()
if you are only updating a single item or a range of items.Another option is to use diffutil . It will compare the original list against the new list and use the new list as the update if there is a change.
Basically, we can use DiffUtil to compare the old data vs new data and let it call notifyItemRangeRemoved, and notifyItemRangeChanged and notifyItemRangeInserted on your behalf.
A quick example of using diffUtil instead of notifyDataSetChanged:
DiffResult diffResult = DiffUtil
.calculateDiff(new MyDiffUtilCB(getItems(), items));
//any clear up on memory here and then
diffResult.dispatchUpdatesTo(this);
//and then, if necessary
items.clear()
items.addAll(newItems)
I do the calculateDiff work off the main thread in case it's a big list.
i got the answer after a long time
SELECTEDROW.add(dt);
notifyItemInserted(position);
SELECTEDROW.remove(position);
notifyItemRemoved(position);
I found out that a really simple way to reload the RecyclerView is to just call
recyclerView.removeAllViews();
This will first remove all content of the RecyclerView and then add it again with the updated values.
The best and the coolest way to add new data to the present data is
ArrayList<String> newItems = new ArrayList<String>();
newItems = getList();
int oldListItemscount = alcontainerDetails.size();
alcontainerDetails.addAll(newItems);
recyclerview.getAdapter().notifyItemChanged(oldListItemscount+1, al_containerDetails);
These methods are efficient and good to start using a basic RecyclerView
.
private List<YourItem> items;
public void setItems(List<YourItem> newItems)
{
clearItems();
addItems(newItems);
}
public void addItem(YourItem item, int position)
{
if (position > items.size()) return;
items.add(item);
notifyItemInserted(position);
}
public void addMoreItems(List<YourItem> newItems)
{
int position = items.size() + 1;
newItems.addAll(newItems);
notifyItemChanged(position, newItems);
}
public void addItems(List<YourItem> newItems)
{
items.addAll(newItems);
notifyDataSetChanged();
}
public void clearItems()
{
items.clear();
notifyDataSetChanged();
}
public void addLoader()
{
items.add(null);
notifyItemInserted(items.size() - 1);
}
public void removeLoader()
{
items.remove(items.size() - 1);
notifyItemRemoved(items.size());
}
public void removeItem(int position)
{
if (position >= items.size()) return;
items.remove(position);
notifyItemRemoved(position);
}
public void swapItems(int positionA, int positionB)
{
if (positionA > items.size()) return;
if (positionB > items.size()) return;
YourItem firstItem = items.get(positionA);
videoList.set(positionA, items.get(positionB));
videoList.set(positionB, firstItem);
notifyDataSetChanged();
}
You can implement them inside of an Adapter Class or in your Fragment or Activity but in that case you have to instantiate the Adapter to call the notification methods. In my case I usually implement it in the Adapter.