ListView getItemViewType() 的复杂示例 [英] Complex example of ListView getItemViewType()

查看:18
本文介绍了ListView getItemViewType() 的复杂示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ListView,它很复杂,因为有 4 种视图类型的可能场景,例如{书、电影、音乐CD、音乐会}

I have a ListView that is complex in that there are possible scenarios for 4 view types e.g. { book, movie, music cd, concert }

目前,为了决定要膨胀的对象等,我得到了与列表行相关的项目.然后我将在对象的类型字段上执行 switch().

Currently, to decide on what object to inflate etc, I get the item that relates to the list row. I will then do a switch() on the type field of the object.

这让我在 getView() 中留下了大量代码和繁重的工作.

This has left me with a lot of code and heavy lifting in the getView().

我说 getItemViewType() 用于返回当前项目的正确视图类型是否正确?

Am I correct in saying that getItemViewType() is used to return the correct view type for the current item?

在哪里可以找到使用这种方法的 ListAdapter 示例?注意:这是为了让我的 ListView 现在变得非常缓慢.

Where would I find an example of a ListAdapter that uses this approach? Note: this is in an attempt to smooth out my ListView that is quite sluggish now.

谢谢

我的适配器

public class MyListAdapter extends BaseAdapter implements ListAdapter {

    private Context ctx;
    private int layoutResourceId;
    private ArrayList<ItemType> items;

    public MyListAdapter(Context context, ArrayList<ItemType> data) {

        this.layoutResourceId = R.layout.timeline_item_row;
        this.ctx = context;
        this.setitems(data);
    }

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

        View row = convertView;
        TimelineHolder holder = null;
        ItemType transaction = getitems().get(position);

        if (row == null) {

            LayoutInflater inflater = ((Activity) ctx).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);

            holder = new TimelineHolder();
            holder.imgActivityIcon = (ImageView)row.findViewById(R.id.imgActivityImageIcon);
            holder.imgActivityLabel = (ImageView)row.findViewById(R.id.imgActivityImageLabel);
            holder.lblMerchantName = (TextView)row.findViewById(R.id.lblMerchantName);
            holder.lblLocation = (TextView)row.findViewById(R.id.lblLocation);
            holder.lblActivityType = (TextView)row.findViewById(R.id.lblActivityType);
            holder.lblActivityLabelUpper = (TextView)row.findViewById(R.id.lblActivityTypeLabel);
            holder.lblTimeSinceActivity = (TextView)row.findViewById(R.id.lblTimeSinceActivity);
            holder.lblActivityAmount = (TextView)row.findViewById(R.id.lblActivityAmount);

            row.setTag(holder);

        }
        else {

            holder = (TimelineHolder) row.getTag();
        }

        // Get/Populate common values here

        String address = "";

        Date hostTime = Helper.parse8601UTC(transaction.getCurrentHostTime());
        Date transactionTime = Helper.parse8601UTC(transaction.getHostTransactionTime());
        String merchantName = transaction.getMerchant().getName();

        holder.lblMerchantName.setText(merchantName);
        holder.lblLocation.setText(address);
        holder.lblTimeSinceActivity.setText(Helper.timeSince(transactionTime, hostTime));
        holder.lblActivityAmount.setText(Helper.doubleToCurrency(transaction.getAmount(), transaction.getCurrency()));

        switch (transaction.getTransactionTypeId()) {

        case TYPE_ONE:

            holder.imgActivityIcon.setImageResource(R.drawable.redemmedicon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Loyalty_Earned);
            holder.lblActivityLabelUpper.setText(R.string.EARNED);
            holder.lblActivityAmount.setText(transaction.getResponsePoints() + " pts");

            break;

        case TYPE_TWO:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Prepay_Redeem_Refund);
            holder.lblActivityLabelUpper.setText(R.string.REDEEMED);

            break;

        case TYPE_THREE:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityLabelUpper.setText(R.string.REFUND);
            holder.lblActivityType.setText(R.string.Prepay_Purchase_Refund);

            break;
        case TYPE_FOUR:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityLabelUpper.setText(R.string.REFUND);
            holder.lblActivityType.setText(R.string.Prepay_Deposit_Refund);

            break;

        case TYPE_FIVE:

            holder.imgActivityIcon.setImageResource(R.drawable.reward_earned_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Reward_Redeemed);
            holder.lblActivityLabelUpper.setText(R.string.REDEEMED);
            holder.lblActivityAmount.setText("");

            break;

        case TYPE_SIX:

            holder.imgActivityIcon
                    .setImageResource(R.drawable.reward_earned_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.redeemed_flag);
            holder.lblActivityType.setText(R.string.Points_Redeemed);
            holder.lblActivityLabelUpper.setText(R.string.REDEEMED);
            holder.lblActivityAmount.setText(transaction.getResponsePoints()
                    + " pts");

            break;

        case TYPE_SEVEN:

            holder.imgActivityIcon.setImageResource(R.drawable.stamp_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.redeemed_flag);
            holder.lblActivityType.setText(R.string.Checked_In);
            holder.lblActivityLabelUpper.setText(R.string.CHECK_IN);
            holder.lblActivityAmount.setText("");

            break;

        case TYPE_EIGHT:

            holder.imgActivityIcon.setImageResource(R.drawable.shared_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.redeemed_flag);
            holder.lblActivityType.setText(R.string.Shared_Coupon);
            holder.lblActivityLabelUpper.setText(R.string.SHARED);
            holder.lblActivityAmount.setText("");

            break;

        case TYPE_NINE:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Prepay_Deposit);
            holder.lblActivityLabelUpper.setText(R.string.DEPOSIT);

            break;

        case TYPE_TEN:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.redeemed_flag);
            holder.lblActivityType.setText(R.string.Prepay_Purchase);
            holder.lblActivityLabelUpper.setText(R.string.PURCHASE);

            break;

        case TYPE_ELEVEN:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Prepay_Redeemed);
            holder.lblActivityLabelUpper.setText(R.string.REDEEMED);

            break;

        case TYPE_TWELVE:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Refund);
            holder.lblActivityLabelUpper.setText(R.string.REFUND);
            holder.lblActivityAmount.setText("");

            break;

        case TYPE_THIRTEEN:

            holder.imgActivityIcon.setImageResource(R.drawable.prepay_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.reversal);
            holder.lblActivityLabelUpper.setText(R.string.REVERSAL);
            holder.lblActivityAmount.setText("");

            break;

        case TYPE_FOURTEEN:

            holder.imgActivityIcon.setImageResource(R.drawable.unlocked_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Check_In_Reward_Unlocked);
            holder.lblActivityLabelUpper.setText(R.string.UNLOCKED);
            holder.lblActivityAmount.setText("");

            break;

        case TYPE_FIFTEEN:

            holder.imgActivityIcon.setImageResource(R.drawable.reward_earned_icon_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText(R.string.Coupon_Received);
            holder.lblActivityLabelUpper.setText(R.string.RECEIVED);
            holder.lblActivityAmount.setText("");

            break;

        default:

            holder.imgActivityIcon.setImageResource(R.drawable.stamp_2x);
            holder.imgActivityLabel.setImageResource(R.drawable.earned_flag);
            holder.lblActivityType.setText("");
            holder.lblActivityLabelUpper.setText("");
            holder.lblActivityAmount.setText("");

            break;
        }

        return row;
    }

    @Override
    public int getCount() {

        return getitems() == null ? 0 : getitems().size();
    }

    @Override
    public Object getItem(int position) {

        return getitems() == null ? null : getitems().get(
                position);
    }

    @Override
    public long getItemId(int position) {

        return layoutResourceId;
    }

    public void addItem(ItemType item, boolean addFirst) {

        if (addFirst) {

            getitems().add(0, item);
        } else {

            getitems().add(item);
        }

        notifyDataSetChanged();
    }

    public ArrayList<ItemType> getitems() {
        return items;
    }

    public void setitems(ArrayList<ItemType> items) {
        this.items = items;
    }

    public int getFirstTransactionId() {

        int result = 0;

        if (items != null && !items.isEmpty()) {

            ItemType txn = items.get(0);
            result = txn.getId();
        }

        return result;
    }

    public int getLastTransactionId() {

        int result = 0;

        if (items != null && !items.isEmpty()) {

            ItemType txn = items.get(items.size() - 1);
            result = txn.getId();
        }

        return result;
    }

    @Override
    public int getViewTypeCount() {

        return 1;
    }

    @Override
    public int getItemViewType(int position) {

        return 0;
    }
}

推荐答案

*** 更新提示 ****
您没有正确实现 getViewTypeCount() 和 getItemViewType().

*** Updated hints ****
You aren't implementing getViewTypeCount() and getItemViewType() correctly.

阅读我在以下链接中提供的教程.我不想重新解释它们,因为我会做得更糟.但请先阅读以下内容,因为您并不真正需要它,因为您只有一种视图类型.

Read the tutorial I provided in links below. I don't want to re-explain them as I'll do a worse job of it. But read below first, because you don't really need that as you only have 1 view type.


选项 1:使用正确的资源图像创建 16 个不同的行.然后在 getView() 方法中调用 getItemViewType(position).打开它,并根据它返回的视图类型扩充正确的行.(教程将解释这一点).这样您就不必继续调用setImageResource"调用,这很昂贵.


Option 1: Create 16-different rows with the correct resource image. Then call getItemViewType(position) inside the getView() method. Do a switch on it, and inflate the correct row based on the view type it returns. (Tutorial will explain this). That way you don't have to keep calling the "setImageResource" call, which is expensive.

选项 2:根据您的视图持有者,您似乎只有 1 个视图,并且您只是更改了 3 个文本字段和 2 个位图.但是每个位图调用都很繁重,您需要创建一个 HashMap 来缓存这些图标.每次调用时,引用哈希映射,如果该项不存在,则创建它,添加它,然后继续.这很重要,因为每次调用 setImageResource() 都在进行位图解码并且需要时间.那才是你真正错误的地方请参阅下面的伪代码.

Option 2: Based on your view holder, it appears that you only have 1 view and you are simply changing 3 text fields and 2 bitmaps. But each bitmap call is heavy, you need to create a HashMap to cache those icons. With each call, reference the hash map, if the item doesn't exist, create it, add it, and proceed. This is important because each call to setImageResource() is doing a bitmap decode and will take time. That is where you real error is See pseudo code below.

private static HashMap<Integer, Bitmap> cache;
static class BitmapCache {
    public static Bitmap get(Integer id) {
        if (cache.containsKey(id)) {
            return cache.get(id);
        } else {
            Bitmap t = BitmapFactory.decodeResource(getContext(), id);
            cache.put(key, t);
            return t;
        }
    }
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder item = null;
    Object o = getItem(position);

    View mRow = convertView;
    if (mRow == null) {
        LayoutInflater li = LayoutInflater.from(getContext());
        switch (getItemViewType(position)) {
        case VIEW_ONLINE:
            mRow = li.inflate(R.layout.row_online, parent, false);
            break;
        default:
            // default to sortable
            mRow = li.inflate(R.layout.row_offline, parent, false);
            break;
        }

        item = new ViewHolder(mRow);
        mRow.setTag(item);
    } else {
        item = (ViewHolder) mRow.getTag();
    }


    item.icon.setImageBitmap(BitmapCache.get(object.key));

    return mRow;
}

* 带有教程的旧答案 *
StackOverflow 上已经有几篇我昨天刚刚浏览过的与此相关的帖子.(见下面的链接).

* Old answer with tutorials *
There are several posts on StackOverflow already that I just went through yesterday related to this. (See links below).

  1. 是的,使用 getItemViewType() 来检索正确的视图类型.据我了解,这里真正的好处在于 getView() 调用期间的视图优化.实现 getItemViewType() 允许 getView() 类型返回正确的缓存视图.
  2. 对膨胀视图内的文本和图像视图使用静态视图持有者模式.您不应该每次都夸大视图,您应该重用 getView() 调用提供的 convertView.
  3. 一定要实现 getViewTypeCount()

这是一个教程,深入解释了如何执行自定义列表视图,包括优化.http://www.vogella.com/articles/AndroidListView/article.html

Here is a tutorial that explains in depth how to perform custom list views including optimizations. http://www.vogella.com/articles/AndroidListView/article.html

这里有两篇 stackoverflow 帖子,它们也讨论了您正在尝试做什么:
1. Android 编程教程 - 教程 5
2. 餐厅计划教程

Here are two stackoverflow posts which also discuss what you are trying to do:
1. Android Programming tutorials - Tutorial 5
2. Restaurant Program Tutorial

这篇关于ListView getItemViewType() 的复杂示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆