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

时间:2019-04-08 14:42:43

标签: java android xamarin

当我尝试从SQLite读取并使用adapter.NotifyDataSetChanged时。我的recyclerView没有看到任何变化。 主要思想是在SQLite中搜索,其中名称包含来自textView的值。 然后重新填充我的适配器。

我创建一个实例

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

然后在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);

直到现在该代码有效。 我的recyclerView中装有来自sqlite的物品。

这是用户在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();
}

当我键入内容时,recyclerView中没有任何变化。 为什么会这样?

例如,我发现此方法可行的唯一方法是在适配器中重置我的项目:

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

为什么会这样?我认为第二种方法不正确。

4 个答案:

答案 0 :(得分:2)

之所以会这样,是因为您正在向mItems分配新对象

第一次创建mItems列表时,会将其传递到适配器上,当您下次从SQLite DB获得响应时,将创建该列表的新实例,因为您将其分配给物体。

您需要做的是

  • 在适配器中创建一个接受adapter.updateItems(newItems)之类的项目的方法
  • 该方法应清除items.clear()之类的列表,然后添加您通过items.addAll(newItems)传递给它的新项目
  • 之后,您可以在适配器本身内调用notifyDataSetChanged(),它将起作用。

在您的适配器中,它看起来像这样

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

然后您可以这样称呼

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

adapter.updateItems(updatedList);

我认为您没有意识到这是按值传递而不是按引用传递的典型情况。

答案 1 :(得分:2)

这是一个byRef问题。 您将内存指针1传递给适配器,并告诉它监视更改。

然后,您加载列表并将内存指针重新指向位置2。 然后告诉适配器它在指针1处监视的内存已更改。

您有两个选择。

  • 通过将新结果与旧结果进行比较来修改原始列表,并根据需要删除和添加
  • 或通过更改适配器内部的项目来告知适配器它正在监视的新内存指针。为swapItems(items)制作方法将起作用。然后在适配器内部调用notifyDataSetChanged。

答案 2 :(得分:1)

您必须在适配器中设置项目, 创建像这样的二传手:

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

然后更新您的搜索方法

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

答案 3 :(得分:0)

设置适配器后通知适配器。

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

adapter = new adpInventoryPreview(mItems);

mRecyclerView.SetAdapter(adapter);

adapter.notifyDataSetChanged();