ListView的复杂例子getItemViewType()

问题描述:

我有一个ListView是复杂的,因为有4个视图类型的可能场景,例如, { book, movie, music cd, concert }ListView的复杂例子getItemViewType()

目前,为了决定什么对象膨胀等,我得到与列表行相关的项目。然后,我将在对象的类型字段上执行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; 
    } 
} 

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

阅读我在下面的链接中提供的教程。我不想重新解释它们,因为我会做更糟的工作。但请先阅读以下内容,因为您不需要这样做,因为您只有1种视图类型。


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

*旧的答案与辅导*
有*上几个职位已经是我刚刚经历昨天去与此相关的。 (请参阅下面的链接)。

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

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

这里有两个计算器的帖子也讨论一下你正在尝试做的:
1. Android Programming tutorials - Tutorial 5
2. Restaurant Program Tutorial

+0

谢谢,也许我需要寻找更难。我目前使用视图模式,但似乎大部分时间ConvertView是空或ID是无效的。 – conor 2013-03-07 17:09:24

+0

如果这些教程不帮助您 - 发布您的自定义适配器,我可以看看它。在我的列表视图中,每行有2个文本视图和2个图像视图,总共有4种不同的行类型。你在视图中使用了很多位图吗? – Cookster 2013-03-07 17:15:50

+0

我刚刚添加了适配器代码。我使用了几张图片,还有其他两张照片。其实,现在只是看图像。 reddemed /赚每个〜4kb,背景是500b。因此,每行大约有4.5kb的图像。这太多了吗? – conor 2013-03-07 17:31:19