简体   繁体   中英

notifyDataSetChanged doesn't work when i am reading from sqlite

When I attempt to read from SQLite and use adapter.NotifyDataSetChanged. I don't see any changes in my recyclerView. The main idea is to search in SQLite where the name contains a value from a textView. Then to repopulate again my adapter.

I create an Instance

 private List<InventoryPreviewClass> mItems;
 private RecyclerView mRecyclerView;
 adpInventoryPreview adapter;

Then inside onCreate() method

mItems = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where CategoryID =" + CategoryID + ""); //Here i am reading from sqlite

mRecyclerView.HasFixedSize = true;
var layout = new GridLayoutManager(this, InventoryRowsPerLine, GridLayoutManager.Vertical, false);
mRecyclerView.SetLayoutManager(layout);
adapter = new adpInventoryPreview(mItems);
mRecyclerView.SetAdapter(adapter);

Until now the code works. My recyclerView is populated with my items from sqlite.

Here is the method when a user types something in TextView

private void EtSearchAlwaysOn_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
{      
   mItems = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where  InventoryItemName like '%" + etSearchAlwaysOn.Text.ToUpper() + "%'");
   adapter.NotifyDataSetChanged();
}

When I am typing something nothing changes in my recyclerView. Why is this happening?

The only way I found that this works is to reset my items inside my adapter for example:

mItems = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where  InventoryItemName like '%" + etSearchAlwaysOn.Text.ToUpper() + "%'");
adapter = new adpInventoryPreview(mItems);
mRecyclerView.SetAdapter(adapter);

Why is this happening? I don't think that the second method is right.

This is happening because you are assigning a new object to mItems

The first time you create the mItems list, you pass it onto your adapter, when the next time you are getting a response from your SQLite DB is creating a new instance of the list since you are assigning it to the object.

What you need to do is

  • Create a method in the adapter that accepts your items like adapter.updateItems(newItems)
  • The method should clear the list like items.clear() and then add the new items you passed it with items.addAll(newItems)
  • After that you can call notifyDataSetChanged() within the adapter itself and it will work.

In your, adapter it will look like this

public void updateItems(final List<InventoryPreviewClass> newItems) {
   items.clear();
   items.addAll(newItems);
   notifyDataSetChanged();
}

and then you can call it like this

updatedList = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where CategoryID =" + CategoryID + "");

adapter.updateItems(updatedList);

I think you missed the point that this is the typical case of pass by value and not pass by reference.

This is a byRef issue. You pass memory pointer 1 to your adapter and tell it to monitor for changes.

Then you load a list and repoint your memory pointer to spot 2. Then you tell adapter that it's monitored memory at pointer 1 has changed.

You have two options.

  • Modify the original list by comparing new results with old results, removing and adding as necessary
  • or Tell the adapter it has a new memory pointer that it is monitoring by changing the items inside the adapter. Making a method for swapItems(items) will work. Then call notifyDataSetChanged inside the adapter.

you have to set items in your adapter, create a setter like this :

 private List<InventoryPreviewClass> mItems; . . . public void setItems(List<InventoryPreviewClass> items) { mItems=items; } 

and then update your search method like this

private void EtSearchAlwaysOn_TextChanged(object sender, 
 Android.Text.TextChangedEventArgs e)
 {      
 mItems = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass 
 where  InventoryItemName like '%" + etSearchAlwaysOn.Text.ToUpper() + "%'");
 adapter.setItems(mItems);
 adapter.NotifyDataSetChanged();
 }

Notify adapter after you set adapter.

mItems = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where InventoryItemName like '%" + etSearchAlwaysOn.Text.ToUpper() + "%'");

adapter = new adpInventoryPreview(mItems);

mRecyclerView.SetAdapter(adapter);

adapter.notifyDataSetChanged();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM