自定义ArrayList Adapter和Cursor的Android怪异行为

时间:2014-05-30 18:33:58

标签: android listview arraylist cursor adapter

我有一个我的对象的自定义ArrayList适配器。在此适配器中,我创建一个带有arrayList deals提供的id的游标。 我对Listview中的项有两种不同的布局,这取决于光标是否包含数据。 问题是上下滚动一段时间会导致listview在不同的项目上多次显示相同的cursordata。 arrayList中的数据显示正确。

pic:http://s1.directupload.net/images/140530/a7cz9ztt.png

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View row = convertView;
    holder = null;
    Cursor cursor = null;

    cursor = db.getDealInfo2ID(deals.get(position).getId());
    int count = cursor.getCount();

    if(row == null){
        holder = new Holder();
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        if(count==0){
            row = inflater.inflate(layoutResourceId, null);
            holder.comment = null;
        }

        else{ 
            row = inflater.inflate(R.layout.card_row_deal_layout, null);
            holder.price = (TextView) row.findViewById(R.id.price);
            holder.icon = (ImageView) row.findViewById(R.id.icon);
            holder.button = (Button) row.findViewById(R.id.toDealButton);
            holder.comment =  (TextView) row.findViewById(R.id.comment);
        }

        holder.name = (TextView)row.findViewById(R.id.dealName);
        holder.degree = (TextView)row.findViewById(R.id.degree);
        holder.thermoColor = row.findViewById(R.id.thermoColor);
        holder.thermoGrey = row.findViewById(R.id.thermoGrey);
        row.setTag(holder);
    }

    else{
        holder = (Holder) row.getTag();
        if(holder.comment==null && count !=0){
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            row = inflater.inflate(R.layout.card_row_deal_layout, parent, false);

            holder.name = (TextView)row.findViewById(R.id.dealName);
            holder.degree = (TextView)row.findViewById(R.id.degree);
            holder.thermoColor = row.findViewById(R.id.thermoColor);
            holder.thermoGrey = row.findViewById(R.id.thermoGrey);

            holder.price = (TextView) row.findViewById(R.id.price);
            holder.icon = (ImageView) row.findViewById(R.id.icon);
            holder.button = (Button) row.findViewById(R.id.toDealButton);
            holder.comment =  (TextView) row.findViewById(R.id.comment);
            row.setTag(holder);
        }
    }

    //ShortCard befüllen
    holder.name.setText(deals.get(position).getName());
    Integer deg = deals.get(position).getDegree();
    setDegreeViews(Math.abs(deg.intValue()),deg);

    if(count!=0){
        // DtailCard befüllen
        fillDetailCard(cursor);

    }
    cursor.close();
    return row;
}

private void fillDetailCard(Cursor cursor) {



    //Preis
    String priceString = cursor.getString(cursor.getColumnIndex(SQLDataBaseHelper.COLUMN_PRICE));
    if(priceString!=null)
        holder.price.setText(priceString);

    //DirectLinkButton
    String url = cursor.getString(cursor.getColumnIndex(SQLDataBaseHelper.COLUMN_DIRECTLINK));
    if(url!=null){
        holder.button.setText(R.string.directDeal);
        holder.button.setBackgroundResource(R.drawable.to_deal_button_background);
        holder.button.setOnClickListener(new ButtonDirectToListener(url, context));
    }
    else{
        holder.button.setText("");
        holder.button.setBackgroundColor(android.R.color.white);
        holder.button.setOnClickListener(null);
    }

    //Kommentar-Anzahl
    holder.comment.setText(cursor.getString(cursor.getColumnIndex(SQLDataBaseHelper.COLUMN_COMMENTCOUNT)));

    //Pic
    String pic = cursor.getString(cursor.getColumnIndex(SQLDataBaseHelper.COLUMN_PIC));
    if(pic!=null){
        holder.icon.setBackground(null);
        holder.icon.setImageDrawable(null);
        picasso.load(pic).error(R.drawable.error).into(holder.icon);
    }
    else{
        holder.icon.setBackground(null);
        holder.icon.setImageDrawable(null);
        int sdk = android.os.Build.VERSION.SDK_INT;
        if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            holder.icon.setBackgroundDrawable(defaultImage);
        } else {
            holder.icon.setBackground(defaultImage);
        }
    }

    cursor.close();
}

我真的不知道问题出在哪里。希望你能帮忙。

1 个答案:

答案 0 :(得分:0)

我仔细阅读了您的代码,我发现它可能会在以下情况中发生:

int count = cursor.getCount(); //returns 0
if(row == null){ //returns false and row is R.layout.card_row_deal_layout

在这种情况下,您省略所有布局设置并跳过调用fillDetailCard。

使用此行if(holder.comment==null && count !=0){,您可以检查布局是否应该从layoutResourceId更改为R.layout.card_row_deal_layout,但您从不检查相反的方式。

看起来像这样:

holder = (Holder) row.getTag();
if(holder.comment==null && count !=0){
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    row = inflater.inflate(R.layout.card_row_deal_layout, parent, false);
    holder = new Holder();
    holder.name = (TextView)row.findViewById(R.id.dealName);
    holder.degree = (TextView)row.findViewById(R.id.degree);
    holder.thermoColor = row.findViewById(R.id.thermoColor);
    holder.thermoGrey = row.findViewById(R.id.thermoGrey);

    holder.price = (TextView) row.findViewById(R.id.price);
    holder.icon = (ImageView) row.findViewById(R.id.icon);
    holder.button = (Button) row.findViewById(R.id.toDealButton);
    holder.comment =  (TextView) row.findViewById(R.id.comment);
    row.setTag(holder);
} else if (holder.comment != null && count == 0) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    row = inflater.inflate(layoutResourceId, null);
    holder = new Holder();
    holder.comment = null;
    holder.name = (TextView)row.findViewById(R.id.dealName);
    holder.degree = (TextView)row.findViewById(R.id.degree);
    holder.thermoColor = row.findViewById(R.id.thermoColor);
    holder.thermoGrey = row.findViewById(R.id.thermoGrey);
    row.setTag(holder);
}

<强>更新

我已经添加了为问题作者建议的布局更改创建新的Holder。

您需要了解ListView重复使用视图组件。如果每个组件都会创建自己的View,以防数百个项目浪费内存。这就是为什么getView()提供有时不为null的convertView的原因。在这些情况下,这意味着您正在重新使用已使用先前数据设置的视图。

因为您使用了2种不同的布局,所以每次都无法重复使用convertView。对于这种情况,您已经实现了if语句if(holder.comment==null && count !=0)。不幸的是,它只是改变布局的一种方式layoutResourceId - &gt; R.layout.card_row_deal_layout当小布局变为更详细的布局时。如果convertView已经R.layout.card_row_deal_layout包含前一项的数据且当前项应为layoutResourceId,则不会更改布局。因此,您需要else if

我希望现在很清楚。