RecyclerView mit EditText geht nicht

  • 8 Antworten
  • Letztes Antwortdatum
S

stikker

Neues Mitglied
2
Ich habe wieder mal ein Problem. Ich habe einen RecyclerView mit unterschiedlichen Rows.
Ich dann die Werte vordefinieren und die werden auch korrekt angezeigt.
Nur leider verliert der Recyler die Daten wenn ich scrolle bzw. speichert irgendwie doppelt ist mir mal aufgefallen.
Und wenn das Display aus geht und man es das smartphone wieder an macht, sind die eingegeben Daten komplett weg und zurück gesetzt.

Ich habe mit die Daten mal ausgeben lassen.
Solange ich oben bin, funktioniert es

onTextChanged Gewicht 3
afterTextChanged Gewicht 3

aber wenn ich runter scrolle und da Daten eingebe kommt als Status
onTextChanged Gewicht 4
onTextChanged Gewicht 13
afterTextChanged Gewicht 4
afterTextChanged Gewicht 13

und wenn ich wieder hoch scrolle führt es 6x aus
onTextChanged Gewicht 4
onTextChanged Gewicht 13
onTextChanged Gewicht 3
afterTextChanged Gewicht 4
afterTextChanged Gewicht 13
afterTextChanged Gewicht 3

wie kann ich das verhindern, so dass immer die richtigen Werte geschrieben werden und nicht mehr gelöscht werden.
Hier mal in Code Schnipsel:

((TraningsplanAnzeigeSatzViewHolder) holder).mGewicht.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.d("Status","onTextChanged Gewicht "+position);
String wert = charSequence.toString();
if (wert.equals("")) wert = "0";
else if (wert.equals(".")) wert = "0";
object.setGewicht(Float.valueOf(wert));
}

public void afterTextChanged(Editable editable) {
Log.d("Status","afterTextChanged Gewicht "+position );
String wert = editable.toString();
if (wert.equals("")) wert = "0";
else if (wert.equals(".")) wert = "0";
object.setGewicht(Float.valueOf(wert));
// mList.notify();
}
});
 
Eine RecyclerView macht genau das was der Name sagt. Views recyclen, also wiederverwenden.
Grob gesagt: nehmen wir an es passen 8 items auf den Bildschirm, dann werden ca 10. views für die items instanziiert. Auch wenn die Datenstruktur hinter deiner RecyclerView 100 Einträge haben sollte.
Beim Scrollen werden die Views die oben rausscrollen unten wieder angehängt und über bindView im Adapter sollten die Daten der items weiter unten eingetragen werden.
D.h. du musst immer dafür sorgen, dass alle Daten deiner items irgendwo persistent gespeichert sind, und nicht nur in den Views selbst.
 
  • Danke
Reaktionen: swa00
Hatte ich auch so raus gelesen, dass es zum Speicher sparen gedacht ist.
Mich wundert nur, dass er es nicht von alleine wieder sinnvoll zurück schreibt.

Wie bekomme ich es hin, dass er die Daten zurück schreibt. Gibt da mal irgendwo ein gutes Tuturial ?

Komisch finde ich auch, dass er mit jedem scrollen offenbar den Textwatcher neu öffnet und hat irgendwann 100 anstatt nur einen.
Und das wiederum erschwert das speichern, weil er ja irgendwann x Positionen erkennt, aber nicht die richtige.
 
Wie schon oben treffend von deek erwähnt , erstelle dir einen (Base) Adapter und ein Array mit deinen Daten.

Sobald zur Laufzeit im Adapter das Element angezeigt wird, nimmst du dir aus deinem Array die dazu gehörigen Daten
und weist sie zu.
 
Zuletzt bearbeitet:
Na ich habe doch meine Datenklasse, wo ich auf die Postion mit
object.setGewicht(Float.valueOf(wert));
meine Daten wieder neu speichere, funktioniert ja auch soweit, nur wie ich sagte, fägt er an mit dem scrollen die
Funktion 1x, 2x, 3x, 4x usw auszuführen, finde ich jetzt auch nicht das Problem, nur will er dann auf
Stelle 3, 13
Stelle 4, 3 , 13
usw. schreiben, wo 2 Stellen davon falsch sind.
 
ich nehme mal an, dass dien Code oben in der bindViewHolder Methode im Adapter ist. Mehr Info haben wir ja nicht.
Das Problem ist, dass du dort jedes mal einen listener ADDest. D.h. die alten bleiben erhalten, damit feuern die auch weiter, weil es ja kein neues Textfeld ist.
In Android gibt es grundsätzlich zwei Arten von listener Methoden an den Objekten add**Listener oder set**Listener. Bei add können mehrere Listener registriert werden, die alle immer feuern. Bei set kann es nur einen Listener geben der ersetzt wird beim nächsten set**Listener call.
Bei Edittext haben wir die add Variante. D.h. du musst dir die Listener entweder so bauen, dass du die Position entsprechend ändern kannst, oder dir die Listener speichern, damit du per removeOnTextChangedListener den alten wieder entfernen kannst.
In beiden Fällen wirst du wohl nicht umhin kommen dir ein Mapping in irgendeiner Form zu speichern um zu wissen welcher Listener für welchen EditText zuständig ist. (absichtlich vage gehalten, ich will dir ja nicht alles vorkaufen ;))
 
  • Danke
Reaktionen: swa00
Habe es jetzt mal entkoppelt:

public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
TextWatcher TextWatcherGewicht = new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
Log.d("Status", "onTextChanged Gewicht " + position);
String wert = charSequence.toString();
if (wert.equals("")) wert = "0";
else if (wert.equals(".")) wert = "0";
mList.get(position).setGewicht(Float.valueOf(wert));
}

public void afterTextChanged(Editable editable) {
}
};


und weiter unten:
((TraningsplanAnzeigeSatzViewHolder) holder).mGewicht.removeTextChangedListener(TextWatcherGewicht);
((TraningsplanAnzeigeSatzViewHolder) holder).mGewicht.addTextChangedListener(TextWatcherGewicht);

aber trotzdem wird es offenbar noch mehrmals ausgeführt
 
Ja klar. Du instanziierst in der Methode lokal deinen Watcher.
Dann willst du den entfernen, aber diese Instanz ist natürlich noch nicht registriert, ist ja eine neue.
Danach addest du diese Instanz zusätzlich.
 
  • Danke
Reaktionen: swa00
Und wie bekomme ich es jetzt hin, dass er die Daten schreibt und den TextWatcher dann schließt ?
Beiträge automatisch zusammengeführt:

Ich denke mal, ich habe die Lösung gefunden, jedenfalls führt er alles nur noch 1x aus und die Daten bleiben stehen.
Ich weise den Handler einfach bei der Klasse RecyclerView.ViewHolder zu.
Was mir gefehlt hat, ich wusste nicht wie man an die Postion kommt. Geht ja mit getAdapterPosition();

Ich hoffe nur es geht jetzt wirklich
Beiträge automatisch zusammengeführt:

Jetzt habe ich noch das Problem, wenn das Display aus geht und ich wieder anschalte verliert der alle eingebene Daten.

Wie kann ich das verhindern ?
 
Zuletzt bearbeitet:
Zurück
Oben Unten