ListView getItemViewType()的复杂示例

我有一个复杂的ListView ,有4种视图types的可能场景,例如{ book, movie, music cd, concert }

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

这让我在getView()有很多代码和繁重的工作。

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

我在哪里可以find使用此方法的ListAdapter的示例? 注意:这是为了平滑我的ListView ,现在非常缓慢。

谢谢

编辑:我的适配器

 public class MyListAdapter extends BaseAdapter implements ListAdapter { private Context ctx; private int layoutResourceId; private ArrayList items; public MyListAdapter(Context context, ArrayList 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 getitems() { return items; } public void setitems(ArrayList 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种视图types。

选项1 :使用正确的资源图像创建16个不同的行。 然后在getView()方法中调用getItemViewType(position)。 对其进行切换,并根据返回的视图types对正确的行进行充气。 (教程将解释这一点)。 这样你就不必继续调用“setImageResource”调用,这很昂贵。

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

 private static HashMap 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上已有几篇post,我昨天刚刚与之相关。 (见下面的链接)。

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

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

这里有两个stackoverflowpost,它们还讨论了你要做的事情:
1. Android编程教程 – 教程5
2. 餐厅计划教程