【问题标题】:Complex example of ListView getItemViewType()ListView getItemViewType() 的复杂示例
【发布时间】:2013-03-08 02:15:25
【问题描述】:

我有一个ListView,它很复杂,因为有 4 种视图类型的可能场景,例如{ book, movie, music cd, concert }

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

这让我在getView() 中留下了很多代码和繁重的工作。

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

我在哪里可以找到使用这种方法的ListAdapter 示例?注意:这是为了让我的ListView 变得更平缓。

谢谢

编辑:我的适配器

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

【问题讨论】:

    标签: android listview


    【解决方案1】:

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

    阅读我在下面链接中提供的教程。我不想重新解释它们,因为我会做得更糟。但请先阅读下文,因为您实际上并不需要它,因为您只有一种视图类型。


    选项 1:使用正确的资源图像创建 16 个不同的行。然后在 getView() 方法中调用 getItemViewType(position)。在它上面做一个开关,并根据它返回的视图类型膨胀正确的行。 (教程将对此进行解释)。这样您就不必一直调用“setImageResource”调用,这很昂贵。

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

    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 上已经有几篇与此相关的帖子。 (见下面的链接)。

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

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

    这里有两个 stackoverflow 帖子,它们还讨论了您要做什么:
    1.Android Programming tutorials - Tutorial 5
    2.Restaurant Program Tutorial

    【讨论】:

    • 谢谢,也许我需要更努力地搜索。我目前使用 viewholder 模式,但似乎大多数时候 ConvertView 要么为 null,要么 id 无效。
    • 如果这些教程对您没有帮助 - 发布您的自定义适配器,我可以查看它。在我的列表视图中,我每行有 2 个文本视图和 2 个图像视图,总共有 4 种不同的行类型。您是否在视图中使用了很多位图?
    • 我刚刚添加了适配器代码。我使用了几张图片作为背景和另外两张。实际上,现在只是看图像。 reddemed/earned 每个约为 4kb,背景为 500b。所以每行大约有 4.5kb 的图像。是不是太过分了?
    • 谢谢。我会在周末研究这个,让你知道我是怎么得到的。感谢您的宝贵时间。
    猜你喜欢
    • 2011-01-17
    • 1970-01-01
    • 2021-07-25
    • 2018-09-27
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多