Android DataAdapter混合数据值

Android DataAdapter混合数据值,android,listview,android-listview,baseadapter,Android,Listview,Android Listview,Baseadapter,我正在为ListView使用自定义数据适配器,它列出了我应用程序中的一些类别。当我添加一个新类别或滚动列表查看每个项目时,不知何故,它并没有为新添加的数据创建一个新项目。这是我的自定义适配器的代码 public class CategoryAdapter extends BaseAdapter { List<Category> mList; Context mContext; public CategoryAdapter(Context context, List<Cate

我正在为ListView使用自定义数据适配器,它列出了我应用程序中的一些类别。当我添加一个新类别或滚动列表查看每个项目时,不知何故,它并没有为新添加的数据创建一个新项目。这是我的自定义适配器的代码

public class CategoryAdapter extends BaseAdapter {

List<Category> mList;
Context mContext;

public CategoryAdapter(Context context, List<Category> data) {
    mList = data;
    mContext = context;
}

@Override
public int getCount() {
    return mList.size();
}

@Override
public Object getItem(int position) {
    if (position < 0 || position >= mList.size())
        return null;
    return mList.get(position);
}

@Override
public long getItemId(int position) {
    if (position < 0 || position >= mList.size())
        return -1;
    return mList.get(position).getId();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    CategoryDelegate del;
    if (convertView == null) {
        System.out.println("CV Null pos: " + position);
        del = new CategoryDelegate(mContext, mList.get(position));
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics());
        del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height));
    } else {
        System.out.println("CV EXIST pos: " + position + " / " + mList.get(position).getTitle() + " =? " + ((CategoryDelegate) convertView).getCategory().getTitle());
        del = (CategoryDelegate) convertView;
    }
    return del;
}

public void setData(List<Category> data) {
    mList = data;
    notifyDataSetChanged();
}

public class CategoryDelegate extends LinearLayout {
    private TextView mTitle;
    private TextView mCount;
    private Category mCategory;

    public CategoryDelegate(Context context, Category category) {
        super(context);
        mCategory = category;

        Resources res = getResources();

        //leftMargin = 11dp; textAlignVCenter; fontSize = 20dp(sp!); color = Color.rgb(149, 155, 171); 
        mTitle = new TextView(context);
        mTitle.setTextColor(Color.rgb(149, 155, 171));
        mTitle.setGravity(Gravity.CENTER_VERTICAL);
        mTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
        mTitle.setText(category.getTitle());
        LayoutParams titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        titleParams.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 11, res.getDisplayMetrics());
        titleParams.weight = 1;
        mTitle.setLayoutParams(titleParams);
        addView(mTitle);

        //rightMargin = 10dp; textAlignVCenter; fontSize = 15dp(sp!); color = Color.rgb(149, 155, 171);
        mCount = new TextView(context);
        mCount.setTextColor(Color.rgb(149, 155, 171));
        mCount.setGravity(Gravity.CENTER_VERTICAL);
        mCount.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
        mCount.setText(String.valueOf(category.getSize()));
        LayoutParams countParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        countParams.gravity = Gravity.RIGHT;
        countParams.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 13, res.getDisplayMetrics());
        mCount.setLayoutParams(countParams);
        addView(mCount);
    }

    public Category getCategory() {
        return mCategory;
    }
}

当我添加一个新的类别或向下滚动到列表时,如果convertView==null{从不工作,我不知道为什么,它会转到现有的convertView,并且在该点之后所有的数据都会混淆。你知道如何使这个适配器工作吗?

如果我像这样更改getView函数

    @Override
public View getView(int position, View convertView, ViewGroup parent) {
    CategoryDelegate del;
    if (convertView == null) {
        del = new CategoryDelegate(mContext, mList.get(position));
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics());
        del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height));
    } else {
        if (((CategoryDelegate) convertView).getId() != mList.get(position).getId()) {
            del = new CategoryDelegate(mContext, mList.get(position));
            int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics());
            del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height));
        } else {
            del = (CategoryDelegate) convertView;
        }
    }
    return del;
}
        public void updateDelegate(Category category) {
        mTitle.setText(category.getTitle());
        mCount.setText(String.valueOf(category.getSize()));
        mCategory = category;
    }
ListView工作正常,但我不确定我做的事情是好是坏。是否有人可以向我解释那里发生了什么。是否有可能导致内存泄漏

编辑:由于我担心内存泄漏,上面的代码恰恰导致内存泄漏,所以我发现一篇关于视图持有者模式的好文章值得一读:

然后我改变了我的代码

    @Override
public View getView(int position, View convertView, ViewGroup parent) {
    CategoryDelegate del;
    if (convertView == null) {
        del = new CategoryDelegate(mContext, mList.get(position));
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics());
        del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height));
    } else {
        if (((CategoryDelegate) convertView).getId() != mList.get(position).getId()) {
            ((CategoryDelegate) convertView).updateDelegate(mList.get(position));
        }
        del = (CategoryDelegate) convertView;
    }
    return del;
}
最后,分类如下:

    @Override
public View getView(int position, View convertView, ViewGroup parent) {
    CategoryDelegate del;
    if (convertView == null) {
        del = new CategoryDelegate(mContext, mList.get(position));
        int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics());
        del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height));
    } else {
        if (((CategoryDelegate) convertView).getId() != mList.get(position).getId()) {
            del = new CategoryDelegate(mContext, mList.get(position));
            int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 67, parent.getResources().getDisplayMetrics());
            del.setLayoutParams(new ListView.LayoutParams(LayoutParams.MATCH_PARENT, height));
        } else {
            del = (CategoryDelegate) convertView;
        }
    }
    return del;
}
        public void updateDelegate(Category category) {
        mTitle.setText(category.getTitle());
        mCount.setText(String.valueOf(category.getSize()));
        mCategory = category;
    }
现在一切都像一个符咒一样工作…

当convertView!=null时,您需要使用新的mList.getposition值更新del,并更新使用该值的任何视图。适配器将回收视图以避免重新实例化整个新视图。因此,当您收到非null convertView时,您将收到一个回收视图。这意味着您'将需要使用该位置的任何新数据更新该视图。注意,回收的视图并不意味着它使用的是同一位置。它可能来自于在完全不同的位置使用的视图

另外,我应该注意到,创建视图的方式并不是一种干净的或推荐的方式。更好的方法是创建一个单独的独立类CategoryDelegate,然后在XML文件中直接使用该类。在其中定义所有属性并扩展该视图

给你一些进一步的阅读: