通过在getview()上添加动态drawable来更新适配器项,以显示错误的数据

时间:2016-03-08 06:28:57

标签: android listview adapter threadpool

我有一个自定义适配器列出我的项目。在每个项目中,我检查数据库并用颜色绘制一些圆圈。

正如您在代码中看到的,我检查convertView==null是否定义了新的viewHolder并绘制了我的项目。但是当我快速滚动listview时,每个绘制的数据(不是标题和文本)都显示错误! 如何在不显示错误数据的情况下管理动态视图创建?!

更新

这是我的尝试:

  1. 我用ui-thread来更新我的列表,但结果是一样的,数据绘图出错了。
  2. 在第二个我尝试用我的对象加载所有数据,这样就不需要在适配器中检查db了。但问题仍然存在......
  3. 最后我创建HashMap<key,LinearLayout>并缓存每个绘制的布局及其项目的ID。因此,如果在我从HashMap加载其视图之前绘制它,并且每个动态布局都只创建一次。但它仍然显示快速滚动的错误数据!我真的不知道下一步该做什么!

    @覆盖     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;
    }
    
  4. 这是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);
            }
    
        }
    

3 个答案:

答案 0 :(得分:1)

您必须在adapter初始化之前从db中选择数据。那么

getItem(position) 

将返回已经“准备好”的项目对象。

您不应将值设置为<{p}内的Views

if (convertView == null) {
    ...
}

此代码仅用于viewHolder初始化。如果convertViewnull,则将其创建为新标记,或将其作为标记读取。 设置viewHolder初始化后必须执行的值,实际上是设置标题的位置。 但是为了提高性能,您不应该在getView的每一步中从db中选择值。你必须准备好一切(已经选中)。

答案 1 :(得分:0)

你可以这样做:

首先在适配器类中创建方法:

public void updateNewData(List<MenuStructureCase> newList){
   this.currentList = newList;
   notifyDataSetChanged();
}

现在,只要您想要更新 ListView ,就可以调用上述方法。

如何使用 CustomAdapter 对象进行调用:

mAdapter.updateNewData(YourNewListHere);

希望这会对你有所帮助。

答案 2 :(得分:0)

  1. 数据渲染需要很长时间,而且在您快速滚动时可能会导致问题。

  2. 您可以重新制作滚动条(例如Gmail:使用拉动刷新),以便在列表视图中一次处理较少的数据量。

  3. 使用RecyclerView代替listview以获得更好的性能

  4. ListView在滚动时重新创建视图。

  5. 可能您可以解释有关您的问题的更多信息,然后我们可以相应地提供输入。