2010-09-30 9 views
28

Oto mój ArrayAdapter. Chciałbym, aby to bardziej efektywne, postępując według schematu ViewHolder:Jak mogę uczynić mój ArrayAdapter zgodny z wzorcem ViewHolder?

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List14.html

ale nie jestem pewien, jak tego dokonać.

UPDATE: ViewHolder Wzór

private class QuoteAdapter extends ArrayAdapter<Quote> { 

    private ArrayList<Quote> items; 
    // used to keep selected position in ListView 
    private int selectedPos = -1; // init value for not-selected 

    public QuoteAdapter(Context context, int textViewResourceId, ArrayList<Quote> items) { 
     super(context, textViewResourceId, items); 
     this.items = items; 
    } 

    public void setSelectedPosition(int pos) { 
     selectedPos = pos; 
     // inform the view of this change 
     notifyDataSetChanged(); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     ViewHolder holder; // to reference the child views for later actions 

     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.mainrow, null); 

      // cache view fields into the holder 
      holder = new ViewHolder(); 
      holder.nameText = (TextView) v.findViewById(R.id.nameText); 
      holder.priceText = (TextView) v.findViewById(R.id.priceText); 
      holder.changeText = (TextView) v.findViewById(R.id.changeText); 

      // associate the holder with the view for later lookup 
      v.setTag(holder); 
     } 
     else { 
      // view already exists, get the holder instance from the view 
      holder = (ViewHolder)v.getTag(); 
     } 

     // change the row color based on selected state 
     if (selectedPos == position) { 
      v.setBackgroundResource(R.drawable.stocks_selected_gradient); 
      holder.nameText.setTextColor(Color.WHITE); 
      holder.priceText.setTextColor(Color.WHITE); 
      holder.changeText.setTextColor(Color.WHITE); 
     } else { 
      v.setBackgroundResource(R.drawable.stocks_gradient); 
      holder.nameText.setTextAppearance(getApplicationContext(), R.style.BlueText); 
      holder.priceText.setTextAppearance(getApplicationContext(), R.style.BlueText); 
      holder.changeText.setTextAppearance(getApplicationContext(), R.style.BlueText); 
     } 

     Quote q = items.get(position); 
     if (q != null) { 
      if (holder.nameText != null) { 
       holder.nameText.setText(q.getSymbol()); 
      } 
      if (holder.priceText != null) { 
       holder.priceText.setText(q.getLastTradePriceOnly()); 
      } 
      if (holder.changeText != null) { 
       try { 
        float floatedChange = Float.valueOf(q.getChange()); 
        if (floatedChange < 0) { 
         if (selectedPos != position) 
          holder.changeText.setTextAppearance(getApplicationContext(), R.style.RedText); // red 
        } else { 
         if (selectedPos != position) 
          holder.changeText.setTextAppearance(getApplicationContext(), R.style.GreenText); // green 
        } 
       } catch (NumberFormatException e) { 
        System.out.println("not a number"); 
       } catch (NullPointerException e) { 
        System.out.println("null number"); 
       } 
       holder.changeText.setText(q.getChange() + " (" + q.getPercentChange() + ")"); 
      } 
     } 
     return v; 
    } 
} 
+0

Stworzyłem narzędzie online do generowania kodu ViewHolder z układu XML: http://www.buzzingandroid.com/tools/android-layout-finder/ – JesperB

Odpowiedz

44

ViewHolder jest w zasadzie statyczna klasa instancji, które kojarzy się z myślą, kiedy to stworzył, buforowanie dziecko postrzega szukasz w górę w czasie wykonywania. Jeśli widok już istnieje, pobierz instancję właściciela i użyj jego pól zamiast wywoływać findViewById.

W twoim przypadku:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View v = convertView; 
    ViewHolder holder; // to reference the child views for later actions 

    if (v == null) { 
     LayoutInflater vi = 
      (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     v = vi.inflate(R.layout.mainrow, null); 
     // cache view fields into the holder 
     holder = new ViewHolder(); 
     holder.nameText = (TextView) v.findViewById(R.id.nameText); 
     holder.priceText = (TextView) v.findViewById(R.id.priceText); 
     holder.changeText = (TextView) v.findViewById(R.id.changeText); 
     // associate the holder with the view for later lookup 
     v.setTag(holder); 
    } 
    else { 
     // view already exists, get the holder instance from the view 
     holder = (ViewHolder) v.getTag(); 
    } 
    // no local variables with findViewById here 

    // use holder.nameText where you were 
    // using the local variable nameText before 

    return v; 
} 

// somewhere else in your class definition 
static class ViewHolder { 
    TextView nameText; 
    TextView priceText; 
    TextView changeText; 
} 

zastrzeżenie: nie próbowałem skompilować to, więc trochę z przymrużeniem oka.

+0

Ten rodzaj ma związek z pytaniem, które wcześniej zadałem widoki recyklingu. Czy znasz jakąkolwiek analizę wydajności związaną z tworzeniem widoków? – Falmarri

+0

@Falmarri Nie konkretnie, nie. Ten szczególny wzór ma na celu uniknięcie nieefektywności 'findViewById' zamiast tworzenia widoku. Byłoby jednak łatwo stworzyć przypadek testowy, aby przeprowadzić własną analizę ponownego użycia widoku w porównaniu z tworzeniem. Podejrzewam, że sama analiza składni XML byłaby wystarczającym powodem do uzasadnienia ponownego użycia. Jeśli widok jest bardzo prosty i zajmuje się programowaniem, nie mam bezpośredniej wiedzy o obciążeniach związanych z tworzeniem. – codelark

+0

świetny przykład kodu. Zaimplementowałem wzorzec widoku. Sprawdź v.setBackgroundResource() czy robię to poprawnie w odniesieniu do wzorca widoku? –

Powiązane problemy