Подтвердить что ты не робот

Порядок строк в Listview изменяется случайно при прокрутке списка в android

У меня есть один ListView и один BaseAdapter. Я загружаю продукты из webservice и показываю в listview.It отображается правильно в listview.

Но когда я просматриваю ListView, отображает строки в случайном положении, значит иногда отображается третий ряд в первой позиции, в средней строке строки отображается последняя позиция и т.д.

Это мой класс адаптера

public class ProductListAdapter extends BaseAdapter implements OnClickListener{

    LayoutInflater inflater;
    ArrayList<Product> arrProducts;
    Context c;

    public ProductListAdapter(Context c, ArrayList<Product> arrProducts) {
        super();
        inflater = LayoutInflater.from(c);
        this.arrProducts = arrProducts;
        this.c = c;
    }

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

    @Override
    public Object getItem(int position) {
        return arrProducts.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View v, ViewGroup parent) {
        Product product = null;
        if(v == null) {
            v = inflater.inflate(R.layout.product_listview_row, null);
            product = (Product) getItem(position);
            v.setTag(product);
        }else {
            product = (Product)v.getTag();
        }

        v.setOnClickListener(this);

        TextView tvProductname = (TextView)v.findViewById(R.id.tvProductname);
        tvProductname.setText(product.getTitle());

        String strReviewCount = product.getReviews();
        TextView tvReviewsCounts = (TextView)v.findViewById(R.id.tvReviews);
        if(strReviewCount != null) tvReviewsCounts.setText(strReviewCount +" Reviews");

        Button btnPrice = (Button)v.findViewById(R.id.btnPrice);
        btnPrice.setText(product.getSellingPrice());

        return v;
    }

    @Override
    public void onClick(View v) {
        Product product = (Product) v.getTag();
        Intent i = new Intent(c, ProductDetails.class);
        i.putExtra(Product.PROD_ID, product.getId());
        startActivity(i);
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount();
    }
}

Это представление ListView в формате XML

<ListView android:id="@+id/lstProducts" style="@style/fill_parent"
        android:dividerHeight="1dp" android:divider="#dbd3c5"
        android:scrollbars="vertical" android:layout_below="@id/layLine"></ListView>

Также, когда я изменяю метод getView() BaseAdapter, как это, он работает нормально

@Override
    public View getView(int position, View v, ViewGroup parent) {
        Product product = null;
        v = inflater.inflate(R.layout.product_listview_row, null);
        product = (Product) getItem(position);
        v.setTag(product);
        v.setOnClickListener(this);

        TextView tvProductname = (TextView)v.findViewById(R.id.tvProductname);
        tvProductname.setText(product.getTitle());

        String strReviewCount = product.getReviews();
        TextView tvReviewsCounts = (TextView)v.findViewById(R.id.tvReviews);
        if(strReviewCount != null) tvReviewsCounts.setText(strReviewCount +" Reviews");

        Button btnPrice = (Button)v.findViewById(R.id.btnPrice);
        btnPrice.setText(product.getSellingPrice());

        return v;
    }

Но проблема в этом типе - я показываю изображение продукта в строке списка, которое я не рассматривал здесь. Используя этот тип кода getView(), метод всегда создает новый вид, когда когда-либо прокручивается listView так что мне нужно загружать изображение снова и снова. Я использовал класс ImageLoader, который использует cash memory для загрузки изображений, но проблема в том, что когда я многократно устанавливал изображение в ImageView, это давало мне out of memory error.

Пожалуйста, помогите мне решить эту проблему.

Спасибо

4b9b3361

Ответ 1

Я приземлился здесь из-за ссылки на правильное решение.

Проблема заключается в том, что вы связываете свой продукт один раз с представлением при создании нового представления. Вы должны вызывать это при каждом вызове getView:

product = (Product) getItem(position);
v.setTag(product);

Но вы могли бы вызвать v.setOnClickListener(this) после создания представления (оно все равно не изменится).

Это должно сделать трюк. Реализация типа вида просто неправильно используется здесь. Я рекомендую прочитать мой ответ здесь...

Ответ 2

Следовательно, согласно рекомендациям, сделанным Knickedi, метод getView() должен выглядеть как:

public View getView(int position, View v, ViewGroup parent) {

    TextView tvProductname;
    TextView tvReviewsCounts;
    Button btnPrice;

    // Phase 1...
    if (v == null) {
        v = inflater.inflate(R.layout.product_listview_row, null);
        v.setOnClickListener(this);

        tvProductname = (TextView)v.findViewById(R.id.tvProductname);
        tvReviewsCounts = (TextView)v.findViewById(R.id.tvReviews);
        btnPrice = (Button)v.findViewById(R.id.btnPrice);

        v.setTag(R.id.tvProductname, tvProductname);
        v.setTag(R.id.tvReviews, tvReviewsCounts);
        v.setTag(R.id.btnPrice, btnPrice);
    }
    else {
        tvProductname = (TextView) v.getTag(R.id.tvProductname);
        tvReviewsCounts = (TextView) v.getTag(R.id.tvReviews);
        btnPrice = (Button) v.getTag(R.id.btnPrice);   
    }

    // Phase 2...
    Product product = (Product) getItem(position);

    tvProductname.setText(product.getTitle());
    btnPrice.setText(product.getSellingPrice());

    String strReviewCount = product.getReviews();
    if(strReviewCount != null)
        tvReviewsCounts.setText(strReviewCount +" Reviews");

    return v;
}