简体   繁体   English

当我从sqlite读取时,notifyDataSetChanged不起作用

[英]notifyDataSetChanged doesn't work when i am reading from sqlite

When I attempt to read from SQLite and use adapter.NotifyDataSetChanged. 当我尝试从SQLite读取并使用adapter.NotifyDataSetChanged时。 I don't see any changes in my recyclerView. 我的recyclerView没有看到任何变化。 The main idea is to search in SQLite where the name contains a value from a textView. 主要思想是在SQLite中搜索,其中名称包含来自textView的值。 Then to repopulate again my adapter. 然后重新填充我的适配器。

I create an Instance 我创建一个实例

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

Then inside onCreate() method 然后在onCreate()方法中

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. 我recyclerView会填充的SQLite我的项目。

Here is the method when a user types something in TextView 这是用户在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. 当我输入内容时,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 发生这种情况是因为您要向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. 第一次创建mItems列表时,将其传递到适配器上,当您下次从SQLite DB获得响应时,由于将列表分配给对象,因此将创建该列表的新实例。

What you need to do is 您需要做的是

  • Create a method in the adapter that accepts your items like adapter.updateItems(newItems) 在适配器中创建一个接受您的项目的方法,例如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) 该方法应清除列表,例如items.clear() ,然后将您通过它传递的新项目与items.addAll(newItems)添加items.addAll(newItems)
  • After that you can call notifyDataSetChanged() within the adapter itself and it will work. 之后,您可以在适配器本身内调用notifyDataSetChanged() ,它将起作用。

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. 这是一个byRef问题。 You pass memory pointer 1 to your adapter and tell it to monitor for changes. 您将内存指针1传递给适配器,并告诉它监视更改。

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. 然后,加载列表并将内存指针指向点2。然后,告诉适配器在指针1处它监视的内存已更改。

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. 为swapItems(items)制作方法将起作用。 Then call notifyDataSetChanged inside the adapter. 然后在适配器内部调用notifyDataSetChanged。

you have to set items in your adapter, create a setter like this : 您必须在适配器中设置项目,像这样创建一个setter:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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