2013-03-07 3 views
10

Ich habe eine ListView, die komplex ist, dass es mögliche Szenarien für 4 Ansichtstypen gibt, z. { book, movie, music cd, concert }Komplexes Beispiel für ListView getItemViewType()

Derzeit, um zu entscheiden, welches Objekt zu aufblasen usw., bekomme ich das Element, das sich auf die Liste Zeile bezieht. Ich mache dann eine switch() auf dem Typ-Feld des Objekts.

Dies hat mich mit einer Menge Code und schweres Heben in der getView() verlassen.

Korrigiere ich, dass getItemViewType() verwendet wird, um den richtigen Ansichtstyp für den aktuellen Artikel zurückzugeben?

Wo finde ich ein Beispiel für eine ListAdapter, die diesen Ansatz verwendet? Hinweis: Dies ist in einem Versuch, meine ListView zu glätten, die jetzt ziemlich träge ist.

Dank

EDIT: Mein Adapter

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

Antwort

8

*** Aktualisiert Hinweise ****
Sie implementieren nicht getViewTypeCount() und getItemViewType() korrekt.

Lesen Sie die Anleitung, die ich in den Links unten zur Verfügung gestellt habe. Ich möchte sie nicht neu erklären, da ich eine schlechtere Arbeit machen werde. Aber lesen Sie zuerst unten, weil Sie das wirklich nicht brauchen, da Sie nur 1 Ansichtstyp haben.


Option 1: Erstellen 16 verschiedene Zeilen mit der richtigen Ressource Bild. Rufen Sie dann getItemViewType (position) in der getView() -Methode auf. Schalten Sie es ein und blähen Sie die richtige Zeile basierend auf dem zurückgegebenen Ansichtstyp auf. (Tutorial wird das erklären). Auf diese Weise müssen Sie nicht ständig den Aufruf "setImageResource" aufrufen, was teuer ist.

Option 2: Auf der Basis Ihrer Ansicht Halter, scheint es, dass Sie nur 1 Aufruf haben, und Sie einfach ändern 3 Textfelder und zwei Bitmaps. Aber jeder Bitmap-Aufruf ist schwer, Sie müssen eine HashMap erstellen, um diese Symbole zwischenzuspeichern. Beziehen Sie sich bei jedem Aufruf auf die Hash-Map, wenn das Element nicht existiert, erstellen Sie es, fügen Sie es hinzu und fahren Sie fort. Dies ist wichtig, da jeder Aufruf von setImageResource() eine Bitmap-Decodierung ausführt und Zeit benötigt. Das ist, wo Sie echte Fehler Siehe Pseudocode unten.

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

* Alte Antwort mit Tutorials *
Es gibt mehrere Beiträge auf Stackoverflow bereits, dass ich durch gestern ging gerade im Zusammenhang mit diesem. (Siehe Links unten).

  1. Ja, verwenden Sie getItemViewType(), um den richtigen Ansichtstyp abzurufen. Wie ich es verstehe, ist der wirkliche Vorteil hier in der Ansichtsoptimierung während des Aufrufs getView(). Durch die Implementierung von getItemViewType() kann der getView() -Typ die korrekte zwischengespeicherte Ansicht zurückgeben.
  2. Verwenden Sie das statische Ansichtshalter-Muster für Text- und Bildansichten innerhalb Ihrer aufgeblähten Ansicht. Sie sollten die Ansicht nicht jedes Mal aufblasen. Sie sollten die vom getView() - Aufruf bereitgestellte convertView erneut verwenden.
  3. Seien Sie sicher, getViewTypeCount()

hier ein Tutorial zu implementieren ist, die in der Tiefe wird erläutert, wie benutzerdefinierte Listenansichten einschließlich Optimierungen durchzuführen. http://www.vogella.com/articles/AndroidListView/article.html

Hier zwei Stackoverflow Beiträge sind, die auch diskutieren, was Sie zu tun versuchen:
1. Android Programming tutorials - Tutorial 5
2. Restaurant Program Tutorial

+0

Danke, vielleicht muss ich härter suchen. Ich verwende derzeit das Viewholder-Muster, aber es scheint, dass die ConvertView meistens Null ist oder die ID ungültig ist. – conor

+0

Wenn diese Tutorials Ihnen nicht helfen - Post Ihren benutzerdefinierten Adapter und ich kann es betrachten. In meiner Listenansicht hatte ich 2 Textansichten und 2 Bildansichten pro Zeile mit insgesamt 4 verschiedenen Zeilentypen. Verwenden Sie aus Ihrer Sicht viele Bitmaps? – Cookster

+0

Ich habe gerade den Adapter-Code hinzugefügt. Ich benutze ein paar Bilder in Ordnung den Hintergrund und zwei andere. Eigentlich nur die Bilder jetzt ansehen. reddemed/verdiente sind ~ 4kb jeder und der Hintergrund ist 500b. Das sind also etwa 4,5 kb Bilder pro Zeile. Ist, dass zu viel? – conor