【问题标题】:Listview rows order changes randomly on scroll of listview in androidListview行顺序在android中的listview滚动时随机变化
【发布时间】:2011-09-26 05:52:03
【问题描述】:

我有一个 ListView 和一个 BaseAdapter。我正在从 web 服务下载产品并显示在 listview 上。它在 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();
    }
}

这是 XML 布局上的 ListView

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

另外,当我像这样更改 BaseAdapter 的 getView() 方法时,它工作正常

@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;
    }

但是这种类型的问题是我在 listview 行上显示产品的图像,我在这里没有考虑过。通过使用这种类型的代码 getView() 方法总是在滚动 listView 时创建新视图 所以我必须一次又一次地下载图像。我使用ImageLoader 类,它使用cash memory 下载图像,但问题是当我将图像设置为 ImageView 多次它给我out of memory error

请帮我解决这个问题。

谢谢

【问题讨论】:

    标签: android listview


    【解决方案1】:

    我来到这里是因为有一个正确解决方案的链接。

    这里的问题是您在创建新视图时将产品绑定到视图一次。您应该在每次调用 getView 时调用它:

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

    但是您可以在创建视图后调用v.setOnClickListener(this)(无论如何它都不会改变)。

    这应该可以解决问题。视图类型的实现在这里被滥用了。我推荐阅读my answer here...

    【讨论】:

    • 我知道我的答案不是确切的使用方式,但出于临时目的,我使用视图类型对其进行了管理。希望您的解决方案有效并得到检查。
    • 谢谢。我希望你不要感到被冒犯,那不是我的本意。这里的问题是人们接受 trick 作为正常和工作,然后当后来出现问题或他们想要使用真正的视图类型实现时会变得非常困惑......我只是想让它清楚,而不是开始谣言;-)
    • 不不,获得确切的解决方案对我也有好处。我个人认为您的答案肯定会奏效,我也会尝试一下。感觉不好从来都不是个案,我也是来学习的。这是从你那里得到的新东西。谢谢。
    • 还有一篇关于适配器的非常好的文章:piwai.info/android-adapter-good-practices
    【解决方案2】:

    因此,根据Knickedi制作的recommendationsgetView()方法应该是这样的:

    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;
    }
    

    【讨论】:

    • 小心public void setTag(int key, Object tag) 已添加到 API 级别 4...
    猜你喜欢
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多