2013-03-07 43 views
10

我有一個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; 
    } 
} 

回答

8

***更新提示****
您還沒有實現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; 
} 

*舊的答案與輔導*
有StackOverflow上幾個職位已經是我剛剛經歷昨天去與此相關的。 (請參閱下面的鏈接)。

  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