通过在 getview() 上添加动态可绘制对象来更新适配器项会导致显示错误的数据
Update adapter items with add dynamic drawable on getview() lead to show wrong data
我有一个列出我的项目的自定义适配器。在每个项目中,我检查数据库并绘制一些带颜色的圆圈。
正如您在代码中看到的那样,我检查 convertView==null
是否定义了新的 viewHolder 并绘制了我的项目。但是当我快速滚动列表视图时,每个绘制的数据(不是标题和文本)都显示错误!
如何在不显示错误数据的情况下管理动态视图创建?!
更新
这是我的尝试:
- 我用 ui-thread 更新了我的列表,但结果是一样的,数据绘制出错了。
- 秒后,我尝试使用 object 加载所有数据,这样就无需检查适配器中的数据库。但问题依然存在...
最后我创建了 HashMap<key,LinearLayout>
并缓存每个绘制的布局及其项目的 ID。因此,如果它是在我从 HashMap 加载它的视图之前绘制的,那么每个动态布局都只会创建一次。但它仍然显示快速滚动的错误数据!真的不知道接下来要做什么了!
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
final MenuStructureCase item = getItem(position);
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = this.mInflater.inflate(R.layout.fragment_menu_item, null);
viewHolder.menu_title = (TextView) convertView.findViewById(R.id.menu_title);
viewHolder.tag_list_in_menu_linear_layout = (LinearLayout) convertView.findViewById(R.id.tag_list_in_menu_linear_layout);
viewHolder.menu_delete = (ImageButton) convertView.findViewById(R.id.image_button_delete);
importMenuTags(viewHolder, getItem(position), viewHolder.tag_list_in_menu_linear_layout);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.menu_title.setText(item.getTitle());
}
return convertView;
}
这是 importMenuTags():
private void importMenuTags(ViewHolder viewHolder, MenuStructureCase item, LinearLayout layout) {
List<String> tags = db.getMenuTags(item.getTitle()); //this present list of string that contain my tags
for (String tag : tags) {
Drawable drawable = getContext().getResources().getDrawable(R.drawable.color_shape);
drawable.setColorFilter(Color.parseColor(each_tag_color), PorterDuff.Mode.SRC_ATOP);
RelativeLayout rl = new RelativeLayout(getContext());
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lparams.setMargins(15, 15, 15, 15);
lparams.width = 50;
lparams.height = 50;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
rl.setBackground(drawable);
} else {
rl.setBackgroundDrawable(drawable);
}
rl.setLayoutParams(lparams);
layout.addView(rl);
}
}
你可以这样做:
首先在适配器内部创建方法 class:
public void updateNewData(List<MenuStructureCase> newList){
this.currentList = newList;
notifyDataSetChanged();
}
现在只要你想更新 ListView.
就调用上面的方法
如何调用 CustomAdapter 的 object:
mAdapter.updateNewData(YourNewListHere);
希望对您有所帮助。
数据呈现需要时间,这可能是您快速滚动时出现问题的原因。
您可以重新滚动(如 Gmail:使用下拉刷新),以便在列表视图中一次处理较少的数据量。
使用 RecyclerView 代替 listview 以获得更好的性能
ListView 在滚动时重新创建视图。
也许您可以详细解释您的问题,然后我们可以相应地提供输入。
在 adapter
初始化之前,您必须 select 来自数据库的数据。这样
getItem(position)
将 return 已经 "ready" item-object。
您不应在
中将值设置为 Views
if (convertView == null) {
...
}
此代码仅用于 viewHolder
初始化。如果 convertView
是 null
或将其作为标签读取,则创建一个新的。
在 viewHolder
初始化后必须设置的值,实际上是在设置标题的位置。
但是为了提高性能,您不应该 select 在 getView
的每个步骤中从 db 获取值。你必须准备好一切(已经 selected)。
我有一个列出我的项目的自定义适配器。在每个项目中,我检查数据库并绘制一些带颜色的圆圈。
正如您在代码中看到的那样,我检查 convertView==null
是否定义了新的 viewHolder 并绘制了我的项目。但是当我快速滚动列表视图时,每个绘制的数据(不是标题和文本)都显示错误!
如何在不显示错误数据的情况下管理动态视图创建?!
更新
这是我的尝试:
- 我用 ui-thread 更新了我的列表,但结果是一样的,数据绘制出错了。
- 秒后,我尝试使用 object 加载所有数据,这样就无需检查适配器中的数据库。但问题依然存在...
最后我创建了
HashMap<key,LinearLayout>
并缓存每个绘制的布局及其项目的 ID。因此,如果它是在我从 HashMap 加载它的视图之前绘制的,那么每个动态布局都只会创建一次。但它仍然显示快速滚动的错误数据!真的不知道接下来要做什么了!@Override public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder; final MenuStructureCase item = getItem(position); if (convertView == null) { viewHolder = new ViewHolder(); convertView = this.mInflater.inflate(R.layout.fragment_menu_item, null); viewHolder.menu_title = (TextView) convertView.findViewById(R.id.menu_title); viewHolder.tag_list_in_menu_linear_layout = (LinearLayout) convertView.findViewById(R.id.tag_list_in_menu_linear_layout); viewHolder.menu_delete = (ImageButton) convertView.findViewById(R.id.image_button_delete); importMenuTags(viewHolder, getItem(position), viewHolder.tag_list_in_menu_linear_layout); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.menu_title.setText(item.getTitle()); } return convertView; }
这是 importMenuTags():
private void importMenuTags(ViewHolder viewHolder, MenuStructureCase item, LinearLayout layout) {
List<String> tags = db.getMenuTags(item.getTitle()); //this present list of string that contain my tags
for (String tag : tags) {
Drawable drawable = getContext().getResources().getDrawable(R.drawable.color_shape);
drawable.setColorFilter(Color.parseColor(each_tag_color), PorterDuff.Mode.SRC_ATOP);
RelativeLayout rl = new RelativeLayout(getContext());
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lparams.setMargins(15, 15, 15, 15);
lparams.width = 50;
lparams.height = 50;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
rl.setBackground(drawable);
} else {
rl.setBackgroundDrawable(drawable);
}
rl.setLayoutParams(lparams);
layout.addView(rl);
}
}
你可以这样做:
首先在适配器内部创建方法 class:
public void updateNewData(List<MenuStructureCase> newList){
this.currentList = newList;
notifyDataSetChanged();
}
现在只要你想更新 ListView.
就调用上面的方法如何调用 CustomAdapter 的 object:
mAdapter.updateNewData(YourNewListHere);
希望对您有所帮助。
数据呈现需要时间,这可能是您快速滚动时出现问题的原因。
您可以重新滚动(如 Gmail:使用下拉刷新),以便在列表视图中一次处理较少的数据量。
使用 RecyclerView 代替 listview 以获得更好的性能
ListView 在滚动时重新创建视图。
也许您可以详细解释您的问题,然后我们可以相应地提供输入。
在 adapter
初始化之前,您必须 select 来自数据库的数据。这样
getItem(position)
将 return 已经 "ready" item-object。
您不应在
中将值设置为Views
if (convertView == null) {
...
}
此代码仅用于 viewHolder
初始化。如果 convertView
是 null
或将其作为标签读取,则创建一个新的。
在 viewHolder
初始化后必须设置的值,实际上是在设置标题的位置。
但是为了提高性能,您不应该 select 在 getView
的每个步骤中从 db 获取值。你必须准备好一切(已经 selected)。