Ejemplo complejo de ListView getItemViewType ()

Tengo un ListView que es complejo en que hay escenarios posibles para 4 tipos de vista por ejemplo { book, movie, music cd, concert }

Actualmente, para decidir sobre qué objeto para inflar etc, consigo el artículo que se relaciona con la fila de la lista. Entonces haré un switch() en el campo tipo del objeto.

Esto me ha dejado con un montón de código y el levantamiento de pesas en el getView() .

¿Estoy correcto al decir que getItemViewType() se utiliza para devolver el tipo de vista correcto para el elemento actual?

¿Dónde puedo encontrar un ejemplo de un ListAdapter que utiliza este enfoque? Nota: esto es en un intento de suavizar mi ListView que es bastante lento ahora.

Gracias

EDIT: Mi adaptador

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

*** Sugerencias actualizadas ****
No está implementando getViewTypeCount () y getItemViewType () correctamente.

Lea el tutorial que proporcioné en los enlaces de abajo. No quiero volver a explicarlo ya que haré un trabajo peor. Pero lea abajo primero, porque usted realmente no necesita eso, ya que sólo tiene 1 tipo de vista.

Opción 1 : cree 16 filas diferentes con la imagen de recurso correcta. A continuación, llame a getItemViewType (posición) dentro del método getView (). Haga un interruptor en él, e infle la fila correcta basada en el tipo de la opinión que devuelve. (Tutorial explicará esto). De esa manera usted no tiene que seguir llamando a la llamada "setImageResource", que es costosa.

Opción 2 : Basado en su titular de vista, parece que sólo tiene 1 vista y simplemente está cambiando 3 campos de texto y 2 mapas de bits. Pero cada llamada bitmap es pesada, necesita crear un HashMap para almacenar en caché esos iconos. Con cada llamada, haga referencia al mapa hash, si el elemento no existe, cree, agregue y continúe. Esto es importante porque cada llamada a setImageResource () está haciendo una decodificación de mapa de bits y tomará tiempo. Ahí es donde se encuentra el verdadero error Ver pseudo código a continuación.

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

* Respuesta antigua con tutoriales *
Hay varios puestos en StackOverflow ya que acabo de pasar ayer relacionados con esto. (Vea los enlaces abajo).

  1. Sí, use getItemViewType () para recuperar el tipo de vista correcto. Según lo entiendo, el beneficio real aquí es en la optimización de la vista durante la llamada getView (). La implementación de getItemViewType () permite que el tipo getView () devuelva la vista en caché correcta.
  2. Utilice el patrón del titular de la vista estática para las vistas de texto e imagen dentro de su vista inflada. Usted no debe inflar la vista cada vez, usted debe reusar el convertView proporcionado por la llamada de getView ().
  3. Asegúrese de implementar getViewTypeCount ()

Aquí hay un tutorial que explica en profundidad cómo realizar vistas personalizadas de lista incluyendo optimizaciones. http://www.vogella.com/articles/AndroidListView/article.html

Aquí hay dos mensajes stackoverflow que también discuten lo que estás tratando de hacer:
1. Tutoriales de programación de Android – Tutorial 5
2. Tutorial del programa de restaurante

  • Actualizar listview dinámicamente con el adaptador
  • Lista personalizada con dos botones en cada fila
  • Averigüe si ListView se desplaza hacia abajo?
  • Disposición personalizada de Android para listview
  • Android ListView - pequeña línea entre los elementos
  • CursorAdapter en ListView
  • OnItemCLickListener no funciona en listview
  • ListView con OnItemClickListener android
  • ¿Puedo usar Pull para actualizar sin utilizar ScrollView / ListView?
  • Android AbsListView $ RecycleBin.addScrapView (AbsListView.java:6588)
  • ListView personalizado de Android, setOnItemSelectedListener no funciona
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.