0

Ich habe eine ListView mit 5+ Arten von Ansichten in Zeilen, das Problem ist: Ich habe 18 Zeilen 10 ist auf dem Bildschirm sichtbar, wenn ich scroll es ist load: 1,2,3 , 4,5,6,7,8,9,10, , , 3, 11, 4 , , 6, 7 Wenn ich tun es ohne ViewHolder alles funktioniert gut, aber alle meine EditText ist weg, weil es neue Ansicht jedes Mal erstellt und ich muss diese Ansicht mit erstellen 40 Zeilen in Zukunft. Der Code:ListViews Recycling-Mechanismus und ViewHolder Konflikt

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Row row = arrayRows.get(position); 

    if (convertView==null) { 
     Log.i("LOG", "convertView == null"); 
     LayoutInflater inflater = (LayoutInflater) this.context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     //setting view holder 
     ViewHolder viewHolder = new ViewHolder(); 
     //build rows 
     if (row.getClass() == RowTextViewEditText.class) { 
      convertView = inflater.inflate(R.layout.row_textview_edittext, null); 
      viewHolder.textView = (TextView) convertView.findViewById(R.id.textViewRowTextViewEditText); 
      viewHolder.editText = (EditText) convertView.findViewById(R.id.editTextRowTextViewEditText); 

      RowTextViewEditText rowTextViewEditText = (RowTextViewEditText) row; 
      viewHolder.textView.setText(rowTextViewEditText.textViewText); 
      viewHolder.editText.setHint(rowTextViewEditText.hint); 
      viewHolder.editText.setText(rowTextViewEditText.editTextText); 
      convertView.setTag(viewHolder); 
     } 
     if (row.getClass() == RowTextViewEditTextTextViewEditText.class) { 
      convertView = inflater.inflate(R.layout.row_textview_edittext_textview_edittext, null); 
      viewHolder.editText = (EditText) convertView.findViewById(R.id.editTextRowTextViewEditTextTextViewEditText); 
      viewHolder.editText2 = (EditText) convertView.findViewById(R.id.editText2RowTextViewEditTextTextViewEditText); 
      viewHolder.textView = (TextView) convertView.findViewById(R.id.textViewRowTextViewEditTextTextViewEditText); 
      viewHolder.textView2 = (TextView) convertView.findViewById(R.id.textView2RowTextViewEditTextTextViewEditText); 

      RowTextViewEditTextTextViewEditText rowEditTextEditText = (RowTextViewEditTextTextViewEditText) row; 
      viewHolder.textView.setText(rowEditTextEditText.textViewText); 
      viewHolder.textView2.setText(rowEditTextEditText.textViewText2); 
      viewHolder.editText.setText(rowEditTextEditText.editTextText); 
      viewHolder.editText2.setText(rowEditTextEditText.editTextText2); 
      convertView.setTag(viewHolder); 
     } 
    } 
    //I have at least 5 types of rows 
    else{ 
     viewHolder = (ViewHolder)convertView.getTag(); 
     Log.i("LOG", "convertView=" + convertView.getTag()); 
    } 
    return convertView; 
} 

Dies ist Logcat:

convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertView == null 
    convertVi[email protected] 
    [email protected]0 
    [email protected]0 
    [email protected]0 
    [email protected]0 
    [email protected]8 
    [email protected]0 

Wie ich aus Reihe 10 convertView nicht null aus irgendeinem Grund zu verstehen, und es ist mir Objekte von 1,2,3,4 zurückkehren .. WARUM ?

Dies ist die ViewHolder Klasse:

public static class ViewHolder { 
    TextView textView; 
    TextView textView2; 
    EditText editText; 
    EditText editText2; 
    Spinner spinner; 
    CheckBox checkBox; 
} 

ich eine Reihe von Ansichten und dann von Position take'em von dort schaffen kann, aber es ist falsch Lösung, und ich will verstehen, warum convertView von Zeile unsichtbar Reihe null ist Danke für den Rat.

+2

Bevor Sie versuchen, die Listenansicht und Ansicht Halter zu lernen. Ich würde das [RecyclerView] (http://developer.android.com/intl/es/reference/android/support/v7/widget/RecyclerView.html) empfehlen. Es kümmert sich um das gesamte Recycling für Sie und ist der empfohlene Weg. – Naveed

+0

Und bitte verwenden Sie keine Klassenübereinstimmungen verwenden enum oder Konstanten – drulabs

+0

drulabs ich benutze Klasse für die Übertragung von Daten von Array zu Zeile nicht für enum arrayRows.add (neue StringTextViewEditTextSpinner (new String [] {"Firma"}, this.getString (R. string.company_name), this.getString (R.string.or_type_company_name_here), arrayCompanies, "", arrayCompanies.get (0), 0)); – adamofsky

Antwort

1

Erstens:

ListView (sowie alle anderen AdapterView s) eine Vorstellung von „Ansichtstypen“, die besser gedacht als „Zeilentypen“ sind. Sie sollten getItemViewType() und getViewTypeCount() verwenden, um Zeilen zu unterscheiden. Dies ermöglicht ListView, die richtigen Zeilenlayouts zu recyceln, wenn es getView() aufruft.

Es ist üblich, getItemViewType() innerhalb von getView() zu verwenden, um festzustellen, welchen Zeilentyp Sie aufblasen (oder recyceln), nicht dieses komische Geschäft, das Sie mit der Überprüfung von Klassentypen haben. Sie sollten diese Klassen nicht einmal erstellen müssen, wenn Sie View-Typen korrekt verwenden.

Normalerweise hat jeder Ansichtstyp seinen eigenen ViewHolder. Die Verwendung derselben ViewHolder-Klasse für eine Vielzahl verschiedener Ansichtstypen ist verwirrend.

Zweitens:

niemals Annahmen über die Reihenfolge der getView() Anrufe tätigen. ListView kann diese Methode zu verschiedenen Zeiten aus verschiedenen Gründen aufrufen; es kann es mit Positionen in steigender oder abnehmender Reihenfolge bezeichnen; Es ist möglicherweise nicht einmal geplant, die Ansicht anzuzeigen, sondern nur für die Messung zu verwenden.

Drittens:

als eine andere Person vorgeschlagen hat, sollten Sie RecyclerView statt ListView mit in Betracht ziehen. Es unterstützt auch verschiedene Ansichtstypen, und das ViewHolder-Muster wird durch Design erzwungen.


Zum besseren Verständnis der Listview, würde ich Sie zu einem Video verweisen genannt The World of ListView. Auch wenn Sie RecyclerView verwenden möchten, gelten die in diesem Video enthaltenen Prinzipien weiterhin.

0

Ok, sieht aus wie viele Menschen nicht Teil der Logik in meinem Code zu verstehen, so werde ich es erklären und als meine eigene Frage zu beantworten. Verwenden von Klassen ist nicht für Aufzählung oder Erkennung von Zeilentypen ist es für die Übertragung und das Abrufen von Daten meiner Zeilen im Adapter. Jede Zeile hat verschiedene Variablen, und ich habe sie in der Reihe setzen und als sich zum Beispiel von der Reihe zu erhalten:

class RowTextViewEditTextCheckBox extends Row{ 
String textViewText; //for set text:name 
String hint; //for set text: please type name here 
String checkBoxTitle; //for set checkBoxTitle 
String editTextText; // for get text after user will fill the field 
boolean checkBoxChecked; //for get result of checkbox when user will check it} 

so sende ich dieses Objekt im Array

arrayRows.add(new RowTextViewEditTextCheckBox(new String[]{"amounts"},this.getString(R.string.burglary),this.getString(R.string.content),this.getString(R.string.amount),"",false)); 

auf die Frage nun zurück: Diese link hilft mir meine Fehler Dank Karakuri für Punkt zu verstehen, mich in Listview „-Ansicht Arten“

Warum nicht alle contentViews von ViewHolder in falschen genommen gesehen stattdessen neue contentView des benötigten Typs erstellen?

Weil ListView den Typ der Zeile erkennt und wenn dieser Typ bereits zuvor erstellt wurde und er sich im Recycler befindet, erstellt er keinen neuen ContentView. Er gibt contentView vom Recycler mit demselben Typ zurück.

Warum ist er den falschen Typ zurück?

Da er nicht weiß, wie viele Arten von Zeilen Sie so standardmäßig haben, ist es 1 Typ. In getViewTypeCount() müssen Sie die Anzahl der Ansichtstypen festlegen.

Wenn ich etwas oder alles falsch verstehe, lass es mich wissen. Das ist ein neuer Code, der wie ein Zauber funktioniert:

@Override 
public int getItemViewType(int position) { 
    Row row = arrayRows.get(position); 
    if (row.getClass()==RowTextViewEditTextSpinner.class){ 
     return 0; 
    } 
    if (row.getClass()==RowTextViewEditTextTextViewEditText.class){ 
     return 1; 
    } 
    if (row.getClass()==RowTextViewEditTextCheckBox.class){ 
     return 2; 
    } 
    if (row.getClass()==RowTextViewEditText.class){ 
     return 3; 
    } 
    if (row.getClass()==RowEditText.class){ 
     return 4; 
    } 
    if (row.getClass()==RowTextView.class){ 
     return 5; 
    } 
    else { 
     return 5; 
    } 
} 
@Override 
public int getViewTypeCount() { 
    return 6;//if types creates by code may be here some logic of counting 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Row row = arrayRows.get(position); 
    int type = getItemViewType(position); 

    //setting view holders 
    ViewHolderTextViewEditTextSpinner viewHolderTextViewEditTextSpinner; 
    ViewHolderTextViewEditTextTextViewEditText viewHolderTextViewEditTextTextViewEditText; 

    //build rows 
    switch (type){ 
     case TEXTVIEW_EDITTEXT_SPINNER: 
      if (convertView==null){ 
       convertView = inflater.inflate(R.layout.row_textview_edittext_spinner, parent, false); 
       viewHolderTextViewEditTextSpinner = new ViewHolderTextViewEditTextSpinner(); 
       viewHolderTextViewEditTextSpinner.textView = (TextView) convertView.findViewById(R.id.textViewRowTextViewEditTextSpinner); 
       viewHolderTextViewEditTextSpinner.editText = (EditText) convertView.findViewById(R.id.editTextRowTextViewEditTextSpinner); 
       viewHolderTextViewEditTextSpinner.spinner = (Spinner) convertView.findViewById(R.id.spinnerRowTextViewEditTextSpinner); 
       convertView.setTag(viewHolderTextViewEditTextSpinner); 
      } 
      else { 
       viewHolderTextViewEditTextSpinner = (ViewHolderTextViewEditTextSpinner)convertView.getTag(); 
      } 
      final RowTextViewEditTextSpinner rowEditTextSpinner = (RowTextViewEditTextSpinner)row; 
      ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, rowEditTextSpinner.spinnerStrings); 
      viewHolderTextViewEditTextSpinner.textView.setText(rowEditTextSpinner.textViewText); 
      viewHolderTextViewEditTextSpinner.editText.setHint(rowEditTextSpinner.hint); 
      viewHolderTextViewEditTextSpinner.editText.setText(rowEditTextSpinner.editTextText); 
      viewHolderTextViewEditTextSpinner.spinner.setAdapter(dataAdapter); 
      viewHolderTextViewEditTextSpinner.spinner.setSelection(rowEditTextSpinner.spinnerSelectedPosition); 
      break; 
     case TEXTVIEW_EDITTEXT_TEXTVIEW_EDITTEXT: 
      if (convertView==null){ 
       convertView = inflater.inflate(R.layout.row_textview_edittext_textview_edittext, parent, false); 
       viewHolderTextViewEditTextTextViewEditText = new ViewHolderTextViewEditTextTextViewEditText(); 
       viewHolderTextViewEditTextTextViewEditText.editText = (EditText) convertView.findViewById(R.id.editTextRowTextViewEditTextTextViewEditText); 
       viewHolderTextViewEditTextTextViewEditText.editText2 = (EditText) convertView.findViewById(R.id.editText2RowTextViewEditTextTextViewEditText); 
       viewHolderTextViewEditTextTextViewEditText.textView = (TextView) convertView.findViewById(R.id.textViewRowTextViewEditTextTextViewEditText); 
       viewHolderTextViewEditTextTextViewEditText.textView2 = (TextView) convertView.findViewById(R.id.textView2RowTextViewEditTextTextViewEditText); 
       convertView.setTag(viewHolderTextViewEditTextTextViewEditText); 
      } 
      else { 
       viewHolderTextViewEditTextTextViewEditText = (ViewHolderTextViewEditTextTextViewEditText)convertView.getTag(); 
      } 
      RowTextViewEditTextTextViewEditText rowEditTextEditText = (RowTextViewEditTextTextViewEditText)row; 
      viewHolderTextViewEditTextTextViewEditText.textView.setText(rowEditTextEditText.textViewText); 
      viewHolderTextViewEditTextTextViewEditText.textView2.setText(rowEditTextEditText.textViewText2); 
      viewHolderTextViewEditTextTextViewEditText.editText.setText(rowEditTextEditText.editTextText); 
      viewHolderTextViewEditTextTextViewEditText.editText2.setText(rowEditTextEditText.editTextText2); 
      break; 

    } 
    return convertView; 
} 

    static public class ViewHolderTextViewEditTextSpinner{ 
    TextView textView; 
    EditText editText; 
    Spinner spinner; 
} 
static public class ViewHolderTextViewEditTextTextViewEditText{ 
    TextView textView; 
    TextView textView2; 
    EditText editText; 
    EditText editText2; 
} 
static public class ViewHolderTextViewEditTextCheckBox{ 
    TextView textView; 
    EditText editText; 
    CheckBox checkBox; 
} 
static public class ViewHolderTextViewEditText{ 
    TextView textView; 
    EditText editText; 
} 
static public class ViewHolderEditText{ 
    EditText editText; 
} 
static public class ViewHolderTextView{ 
    TextView textView; 
} 

Bitte lassen Sie mich wissen, wenn eine bessere Lösung sein kann, oder wenn diese falsche Lösung ist