Android – EditTexts dentro de ListView vinculado a Custom ArrayAdapter – manteniendo un registro de los cambios

Tengo una actividad de Android en la que tengo un ListView enlazado a un ArrayAdapter personalizado. Cada fila del ListView tiene dos campos EditText (numérico).

El ArrayAdapter se rellena inicialmente de un DB de SQLite. Sin embargo, el usuario puede agregar una fila al final de ListView, o (pulsando una fila) borrar cualquier fila de ListView. Cuando se pulsa el botón "Guardar", sus cambios se mantienen.

Estoy haciendo un seguimiento de los cambios a medida que se realizan adjuntando un CustomTextWatcher para el evento AfterTextChanged () a cada EditText en el método getView () de ArrayAdapter (pasando el EditText y el objeto correspondiente en la lista de elementos del ArrayAdapter) Propiedad de ese objeto al contenido del EditText. Esto es para que al guardar simplemente pueda iterar a través de la lista de objetos subyacente y hacer los cambios de DB apropiados, sabiendo que la lista de objetos está actualizada.

Código para la clase de adaptador y CustomTextWatcher:

private class CustomAdapter extends ArrayAdapter<DataItem> { private ArrayList<DataItem> items; public CustomAdapter(Context context, int textViewResourceId, ArrayList<DataItem> items) { super(context, textViewResourceId, items); this.items = items; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; DataItem wed = items.get(position); if (v == null) { LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.log_exercise_row, null); } if(wed != null) { EditText text1 = (EditText) v.findViewById(R.id.text1); EditText text2 = (EditText) v.findViewById(R.id.text2); text1.addTextChangedListener(new CustomTextWatcher(text1,wed)); text2.addTextChangedListener(new CustomTextWatcher(text2,wed)); int weight = wed.getWeight(); if(weight != -1) { text1.setText(weight+""); } int reps = wed.getReps(); if(reps != -1) { text2.setText(reps+""); } } return v; } private class CustomTextWatcher implements TextWatcher { private EditText EditText; private DataItem item; public CustomTextWatcher(EditText e, DataItem item) { this.EditText = e; this.item = item; } @Override public void afterTextChanged(Editable arg0) { String text = arg0.toString(); if(text != null && text.length() > 0) { int val; try { val =Integer.parseInt(text); } catch(NumberFormatException e) { val=-1; } if(EditText.getId()==R.id.weightEditText) { item.setWeight(val); } else if(EditText.getId()==R.id.repsEditText) { item.setRepetitions(val); } } } 

Todo esto funciona bien, excepto cuando se agregan o eliminan elementos cuando se produce una duplicación no deseada del contenido de EditarTexto.

Para ilustrar con un ejemplo:

Comienza con 3 filas, EditText está todo vacío
En la fila 2, escriba '5', '6'
Haga clic en 'Más' -> Agrega una fila (vacía) al final. Ahora 4 filas.
Eliminar la última fila-> 3 filas se muestran, pero 2 ª y 3 ª filas ahora muestran '5', '6' -> ???????

Parece que la posición relativa de los objetos EditText dentro de ListView no es estable después de volver a enlazar que está causando el problema. Por ejemplo, el objeto EditText 'X' comienza en la posición 3 y, a continuación, después de un rebind, está en la posición 1, pero todavía tiene un CustomTextWatcher conectado a él haciendo referencia al objeto de datos en la posición 3. El otro problema es que addTextChangedListener () Afectan a los TextWatchers ya conectados al EditText.

Soy bastante nuevo para Android, así que no estoy seguro si hay un mejor enfoque para resolver mi problema. Cualquier ayuda es apreciada.

Parece que una clase personalizada ('ViewHolder') era lo que necesitaba para mantener las referencias entre un EditText y su objeto de datos asociados correctamente sincronizados en cada 'bind' de los datos. Además, al colocar las llamadas del detector de eventos cuando el objeto convertView era nulo en el método getView (), sólo se añadía un oyente por objeto EditText.

Gracias a http://www.vogella.de/articles/AndroidListView/article.html#listsactividad por señalarme en la dirección correcta.

 public class CustomAdapter extends ArrayAdapter<DataItem> { private ArrayList<DataItem> items; private Activity Context; public CustomAdapter(Activity context, int textViewResourceId, ArrayList<DataItem> items) { super(context, textViewResourceId, items); this.items = items; this.Context = context; } static class ViewHolder { protected EditText weight; protected EditText reps; } public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; DataItem wed = items.get(position); if (v == null) { LayoutInflater inflator = Context.getLayoutInflater(); v = inflator.inflate(R.layout.log_exercise_row, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.text1 = (EditText) v.findViewById(R.id.text1); viewHolder.text2 = (EditText) v.findViewById(R.id.text2); viewHolder.text1.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text1)); viewHolder.text2.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text2)); v.setTag(viewHolder); viewHolder.text1.setTag(wed); viewHolder.text2.setTag(wed); } else { ViewHolder holder = (ViewHolder) v.getTag(); holder.text1.setTag(wed); holder.text2.setTag(wed); } ViewHolder holder = (ViewHolder) v.getTag(); // set values if(wed.getWeight() != -1) { holder.text1.setText(wed.getWeight()+""); } else { holder.weight.setText(""); } if(wed.getRepetitions() != -1) { holder.text2.setText(wed.getRepetitions()+""); } else { holder.reps.setText(""); } return v; } 
  • Android: conflicto de ID cuando se crean 3 pestañas o más
  • ¿Cómo llenar un ListView con una ArrayList?
  • ¿Cómo trabajar, cuando listview dentro del scrollview?
  • Estado de comprobación de ListView Viewholder
  • Casilla de verificación desmarcada cuando hago scrolllistview en Android
  • OnItemClickListener y OnClickListener no funcionan para ListView
  • Android: colocar anuncio en la parte inferior de la pantalla
  • Referencia de diseño duplicada en la vista de lista
  • Android API 21 - vista de pie de página IndexOutOfBoundsException
  • No se puede utilizar SimpleAdapter en un ListFragment
  • Listview conjunto adaptador fragmento nullpointerexception
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.