使用数据作为 Map 的 notifyDataSetChanged 后 Android ListView 不刷新
Posted
技术标签:
【中文标题】使用数据作为 Map 的 notifyDataSetChanged 后 Android ListView 不刷新【英文标题】:Android ListView not refreshing after notifyDataSetChanged with data as Map 【发布时间】:2014-08-18 16:10:37 【问题描述】:我使用了带有地图值的列表适配器作为数据。当我使用adapter.notifyDataSetChanged();
时,列表中的数据没有更新。但是,如果我用 ArrayList 替换 Map 一切正常。以下是我的适配器代码。
public class CategoryAdapter extends BaseAdapter
ArrayList<Category> list = new ArrayList<Category>();
Context context;
public CategoryAdapter(Context context, Map<String, Category> categories)
this.context = context;
list.clear();
list.addAll(categories.values());
@Override
public int getCount()
return list.size();
@Override
public View getView(int position, View convertView, ViewGroup parent)
final ViewHandler handler;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.category_list_item, null);
handler = new ViewHandler();
handler.name = (TextView) convertView.findViewById(R.id.name);
handler.count = (TextView) convertView.findViewById(R.id.count);
convertView.setTag(handler);
else
handler = (ViewHandler) convertView.getTag();
Category category = list.get(position);
handler.name.setText(category.getMenuName());
handler.count.setText(category.getCount() + "");
if (category.getCount() <= 0)
handler.count.setVisibility(View.INVISIBLE);
else
handler.count.setVisibility(View.VISIBLE);
return convertView;
我的活动代码是
private void loadCategories()
sampleDB = openOrCreateDatabase(AppConstants.DB_NAME, MODE_PRIVATE,
null);
Cursor menuCursor = sampleDB.rawQuery("select * from menu", null);
categories.clear();
while (menuCursor.moveToNext())
String menu = menuCursor.getString(menuCursor
.getColumnIndex("name"));
String id = menuCursor.getString(menuCursor.getColumnIndex("id"));
Category category = new Category(menu, id);
categories.put(id, category);
menuCursor.close();
categoryAdapter.notifyDataSetChanged();
在oncreate()
方法中我已经声明适配器如下
categoryAdapter = new CategoryAdapter(context, categories);
categoryList.setAdapter(categoryAdapter);
loadCategories();
每次我点击刷新按钮时,它都会调用loadCategories();
方法。
在相同的代码中,如果我用 ArrayList 替换 Map 一切正常。
现在我的问题是为什么 List 不刷新 Map 值。请给我澄清一下。
提前致谢。
【问题讨论】:
你在哪里添加/更改categoryAdapter
的内容
对不起。 categoryAdapter
是使用 categories
映射声明的。请参阅我更新的问题。每次我点击刷新按钮 loadCategories() 都会调用。并且在那个类别中值发生变化。
是onCreate()
唯一创建CategoryAdapter
? 实例的地方。如果是这样,您的categoryAdapter
的ArrayList<Category> list
不会更新
是的,oncreate()
是为CategoryAdapter
创建实例的唯一地方。即使我使用notifyDataSetChanged()
,ArrayList<Category> list
也不会生效。
那是因为你没有更新适配器实例的列表。让我想出一个我认为可行的答案。请稍等片刻...
【参考方案1】:
您必须向 CategoryAdapter
添加一个方法来更改实例的列表,如下所示
public class CategoryAdapter extends BaseAdapter
ArrayList<Category> list = new ArrayList<Category>();
Context context;
public CategoryAdapter(Context context, Map<String, Category> categories)
this.context = context;
list.clear();
list.addAll(categories.values());
@Override
public int getCount()
return list.size();
//ADD THIS METHOD TO CHANGE YOUR LIST
public void addItems(Map<String, Category> categories)
list.clear();
list.addAll(categories.values());
@Override
public View getView(int position, View convertView, ViewGroup parent)
final ViewHandler handler;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.category_list_item, null);
handler = new ViewHandler();
handler.name = (TextView) convertView.findViewById(R.id.name);
handler.count = (TextView) convertView.findViewById(R.id.count);
convertView.setTag(handler);
else
handler = (ViewHandler) convertView.getTag();
Category category = list.get(position);
handler.name.setText(category.getMenuName());
handler.count.setText(category.getCount() + "");
if (category.getCount() <= 0)
handler.count.setVisibility(View.INVISIBLE);
else
handler.count.setVisibility(View.VISIBLE);
return convertView;
并像这样更改您的 loadCategories(请注意,我在 notifyDataSetChanged()
之前调用 addItems()
private void loadCategories()
sampleDB = openOrCreateDatabase(AppConstants.DB_NAME, MODE_PRIVATE,
null);
Cursor menuCursor = sampleDB.rawQuery("select * from menu", null);
categories.clear();
while (menuCursor.moveToNext())
String menu = menuCursor.getString(menuCursor
.getColumnIndex("name"));
String id = menuCursor.getString(menuCursor.getColumnIndex("id"));
Category category = new Category(menu, id);
categories.put(id, category);
menuCursor.close();
//ADD CALL TO addItems TO UPDATE THE LIST OF THE categoryAdapter instance
categoryAdapter.addItems(categories);
categoryAdapter.notifyDataSetChanged();
【讨论】:
工作得很好。谢谢。 不使用addItems()
如果我用public CategoryAdapter(Context context, ArrayList<Category> categories) this.context = context; list=categories;
替换构造函数,它可以正常工作,但不能使用Map。你能解释一下吗?
你在loadCategories()
中调用那个构造函数吗?
没有。更新类别 ArrayList 后,我调用了 notifyDataSetChanged(),它工作正常。
哦,我现在明白了。在您的构造函数中,您将categories
分配给list
。所以如果你更新你的categories
,你更新你的list
然后你的数据就改变了【参考方案2】:
你试过说:
categoryList.setAdapter(null);
categoryList.setAdapter(categoryAdapter);
【讨论】:
以上是关于使用数据作为 Map 的 notifyDataSetChanged 后 Android ListView 不刷新的主要内容,如果未能解决你的问题,请参考以下文章
如何解决“不能使用 null 作为映射键!”使用 Group_Map 在 Python 3 中出现 Spark.SQL 错误