2012-11-08 7 views
38

Nauczyłem się, że aby zmaksymalizować wydajność dzięki Android Listview, powinieneś mieć tylko tyle zawyżonych widoków "rzędu", ile potrzeba, aby zmieścić się na ekranie. Gdy widok zniknie z ekranu, należy go ponownie użyć w metodzie getView, sprawdzając, czy convertView ma wartość null, czy nie.Ponowne wykorzystywanie widoków w widoku list w systemie Android z 2 różnymi układami

Jak jednak wdrożyć ten pomysł, gdy potrzebujesz 2 różnych układów dla listy? Powiedzmy, że jest to lista zamówień, a 1 układ dotyczy zamówień zakończonych, a drugi układ dotyczy zamówień procesowych.

Oto przykładowy samouczek idei, której używa mój kod. W moim przypadku, chciałbym mieć układy 2 rząd: R.layout.listview_item_product_complete i 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; 
} 
+0

Sam ostatnio napotkałem ten problem. Używałem 2 różnych układów do wypełnienia listy, co zaowocowało kompletną anarchią. Raz po raz sprawdzałem swój kod, ale nie mogłem zrozumieć, dlaczego niewłaściwy układ został ponownie użyty. Ostatecznie zdecydowałem, że pozostanie tylko jeden * układ na liście, ale silnie modyfikuję ten widok na podstawie typu elementu. Istnieje wiele możliwości edycji elementów w kodzie. –

Odpowiedz

83

Musisz pozwolić adaptera widok recyklingowa wiedzą, że istnieje więcej niż jeden układ i jak odróżnić dwa dla każdego wiersza. Wystarczy zastąpić te metody:

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

Incorporate getItemViewType() wewnątrz getView(), tak:

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... 

zegarka Android Romain Guy discuss the view recycler w Google rozmów.

+0

OK, więc właściciel służy jako kopia wskaźników do różnych widoków zawartych w układzie wiersza. W moim przypadku oba układy będą miały te same typy pól (tylko sformatowane inaczej). Więc potrzebuję tylko jednego właściciela, prawda? A jeśli jeden układ miał TextView i ImageView, podczas gdy drugi miał 2 TextView, potrzebowałbym 2 różnych uchwytów, nie? – jamis0n

+2

"W moim przypadku oba układy będą miały te same typy pól (tylko sformatowane inaczej), więc potrzebuję tylko jednego właściciela." Tak, to prawda. "A jeśli jeden układ miał TextView i ImageView, podczas gdy drugi miał 2 TextView, potrzebowałbym 2 różnych uchwytów, nie?" Możesz mieć dwa różne ViewHolders lub możesz połączyć ViewHolders, ale dostęp tylko do odpowiednich członków dla każdego układu. Czy to ma sens? – Sam

+0

Jesteś mężczyzną! To nigdy nie działa za pierwszym razem! Z wyjątkiem twoich wskazówek Haha ... Tak więc dla mojego zrozumienia, posiadacz po prostu trzyma wskaźnik do każdego widoku w układach rzędów. Otrzymuje je z nowo zawyżonych układów, gdy ConvertView ma wartość Null LUB magicznie podnosi te wskaźniki z wywołania do 'holder = (ViewHolder) convertView.getTag();'. Czy rozumiem to? Zaktualizowałem też mój ostatni kod powyżej ... Jeszcze raz dziękuję! – jamis0n

9

Nie trzeba samemu projektować rozwiązania, wystarczy zastąpić metodę getItemViewType() i metodę getViewTypeCount().

Zobacz następujący wpis na blogu na przykład http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

Ponieważ blog wyjaśnia, Android faktycznie nie gwarancja że getView otrzyma prawidłowy typ widoku.

+1

Nie widziałem tego problemu ...Czy to twój blog (zauważyłem, że jest napisany przez "Andy")? Założę się, że 'getDirItem()' jest wadliwy, a nie recykler widoku. – Sam

+0

Tak, to mój blog. Zakład - Ile? :) Poważnie, twój komentarz sprawił, że wątpię w siebie, więc poszedłem i potrójnie sprawdziłem mój kod + dodałem trochę więcej debugowania. Zdecydowanie jest tak, że Android czasami mija niewłaściwy widok. Wskazówką jest to, że używam metody getItemViewType() w getView(), aby określić typ. Nawet jeśli było to błędne, chyba że zwraca wyniki losowe (całkiem na pewno, że tak nie jest!), To Android przechodzi przez niewłaściwy widok. – Andy

+0

Nie słyszałem o tym problemie przed ... Czy masz jakieś niezależne źródła, aby to potwierdzić? Nie widzę tego sam i nie mogę znaleźć. Bez obejrzenia całego kodu nie można zobaczyć, co naprawdę dzieje się w kodzie. Ale na początek jakie są wartości dla 'TYPE_DIR' i' TYPE_PIC'? – Sam

Powiązane problemy