Повторное использование представлений в Android Listview с 2 различными макетами
Я узнал, что для максимизации эффективности с помощью списков просмотра Android вы должны иметь только столько завышенных представлений "строк", сколько необходимо для размещения на экране. После того, как вид переместился за пределы экрана, вы должны повторно использовать его в своем getView
метод, проверяя, если convertView
является нулевым или нет.
Тем не менее, как вы можете реализовать эту идею, когда вам нужно 2 разных макетов для списка? Допустим, это список заказов, и 1 макет предназначен для выполненных заказов, а другой макет - для обрабатываемых заказов.
Это пример учебника идеи, которую использует мой код. В моем случае у меня было бы 2 ряда строк: R.layout.listview_item_product_complete
а также R.layout.listview_item_product_inprocess
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
if(getItemViewType(position) == COMPLETE_TYPE_INDEX) {
convertView = mInflator.inflate(R.layout.listview_item_product_complete, null);
holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_complete);
holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_complete);
}
else { // must be INPROCESS_TYPE_INDEX
convertView = mInflator.inflate(R.layout.listview_item_product_inprocess, null);
holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_inprocess);
holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_inprocess);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
thisOrder = (Order) myOrders.getOrderList().get(position);
// If using different views for each type, use an if statement to test for type, like above
holder.mNameTextView.setText(thisOrder.getNameValue());
holder.mImgImageView.setImageResource(thisOrder.getIconValue());
return convertView;
}
public static class ViewHolder {
public TextView mNameTextView;
public ImageView mImgImageView;
}
2 ответа
Вам нужно сообщить представителю адаптера представления о том, что существует более одного макета и как различать два для каждого ряда. Просто переопределите эти методы:
@Override
public int getItemViewType(int position) {
// Define a way to determine which layout to use, here it's just evens and odds.
return position % 2;
}
@Override
public int getViewTypeCount() {
return 2; // Count of different layouts
}
инкорпорировать getItemViewType()
внутри getView()
, как это:
if (convertView == null) {
// You can move this line into your constructor, the inflater service won't change.
mInflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
if(getItemViewType(position) == 0)
convertView = mInflater.inflate(R.layout.listview_item_product_complete, parent, false);
else
convertView = mInflater.inflate(R.layout.listview_item_product_inprocess, parent, false);
// etc, etc...
Посмотрите, как Ромэн Гай из Android обсуждает вопрос об утилизации в Google Talks.
Не нужно самостоятельно разрабатывать решение, просто переопределите getItemViewType() и getViewTypeCount().
См. Следующий пост в блоге для примера http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html
Как объясняется в блоге, Android фактически не гарантирует, что getView получит правильный тип просмотра.