ELITE ELITE - 6 months ago 26
Android Question

Strange ListAdapter behavior

I am using

BaseAdapter
for displaying some items.

I don't want to change the text for item at position zero.

So
getView
method of my
BaseAdapter
looks like

public View getView(int position, View view, ViewGroup parent) {
try {
if(view == null) {
view = LayoutInflater.from(context).inflate(R.layout.item_bill, parent, false);
}
Log.e("BillAdapter", "Position :: " + position);
if(position == 0) {
Log.e("BillAdapter", "Position zero. Not changing values....");
} else {
Bill bill = items.get(position);
Log.e("BillAdapter", position + " :: " + bill.toString());
TextView textDate = (TextView) view.findViewById(R.id.text_date);
textDate.setText(bill.getDate());
TextView textPaidAmount = (TextView) view.findViewById(R.id.text_paid_amount);
textPaidAmount.setText(String.format("%2.2f", bill.getPaidAmount()));
}
} catch (Exception ex) {
Log.e("BillAdpater", Log.getStackTraceString(ex));
}
return view;
}


But my output is

Output

I'm using the same logic in my all applications and it works. I don't know whats wrong in this.

It reflects the last value at first position.

I tried to rebuild the project, clean the project, but no success.

Thanks in advance.

Answer

your problem is ListView's recycling mechanism. please read this to get more info.

you can solve your problem with setting data in if statement, so your getView must be like :

try {
        if(view == null) {
            view = LayoutInflater.from(context).inflate(R.layout.item_bill, parent, false);
        }
        Log.e("BillAdapter", "Position :: " + position);
        TextView textDate = (TextView) view.findViewById(R.id.text_date);
        TextView textPaidAmount = (TextView) view.findViewById(R.id.text_paid_amount);

        if(position == 0) {
            textDate.setText("Date");
            textPaidAmount.setText("Paid Amount");
        } else {
            Bill bill = items.get(position);
            Log.e("BillAdapter", position + " :: " + bill.toString());
            textDate.setText(bill.getDate());

            textPaidAmount.setText(String.format("%2.2f", bill.getPaidAmount()));
        }
    } catch (Exception ex) {
        Log.e("BillAdpater", Log.getStackTraceString(ex));
    }

when you set one info in if statement in listView you MUST set default or another value in else too, if you don't set that as recycling mechanism happened your value changed with one random position after scrolling.

EDIT :: Refer image for detailed understanding

Details

it's better to use ViewHolder pattern in your adapter class: you can use following code.

in getView use :

 try {

       ViewHolder viewHolder;

       if(view == null) {
           view = LayoutInflater.from(context).inflate(R.layout.item_bill, parent, false);
           viewHolder = new ViewHolder();
           viewHolder.textPaidAmount = (TextView) view.findViewById(R.id.text_paid_amount);
           viewHolder.textDate =  (TextView) view.findViewById(R.id.text_date);

            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }

            Log.e("BillAdapter", "Position :: " + position);

            if(position == 0) {
                holder.textDate.setText("Date");
                holder.textPaidAmount.setText("Paid Amount");
            } else {
                Bill bill = items.get(position);
                Log.e("BillAdapter", position + " :: " + bill.toString());
                holder.textDate.setText(bill.getDate());
                holder.textPaidAmount.setText(String.format("%2.2f", bill.getPaidAmount()));
            }
        } catch (Exception ex) {
            Log.e("BillAdpater", Log.getStackTraceString(ex));
        }

and ViewHolder class is :

class ViewHolder {
    TextView textDate;
    TextView textPaidAmount;
}
Comments