title: Android - EditTexts within ListView bound to Custom ArrayAdapter - keeping track of changes
body: <p>I have an Android activity in which I have a ListView bound to a custom ArrayAdapter. Each row of the ListView has two EditText (numeric) fields. </p>
  
  <p>The ArrayAdapter is initially populated from an SQLite DB. However the user can add a row at the end of the ListView, or (by long-pressing on a row) delete any row in the ListView. When they hit the 'Save' button, their changes are persisted.</p>
  
  <p>I am keeping track of changes as they are made by attaching a CustomTextWatcher for the AfterTextChanged() event to each EditText in the ArrayAdapter's getView() method (passing in the EditText and the corresponding object in the ArrayAdapter's item list) and then setting the matching property of that object to the content of the EditText. This is so that on saving I can simply iterate through the underlying object list and make the appropriate DB changes, knowing that the object list is up-to-date.</p>
  
  <p>Code for the adapter class and the CustomTextWatcher:</p>
  
  <pre><code>private class CustomAdapter extends ArrayAdapter&lt;DataItem&gt; {
      private ArrayList&lt;DataItem&gt; items;
  
      public CustomAdapter(Context context, int textViewResourceId, ArrayList&lt;DataItem&gt; 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 &amp;&amp; text.length() &gt; 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);
              }
          }
      }
  </code></pre>
  
  <p>This all works fine except when items are added or deleted when unwanted duplication of EditText content happens. </p>
  
  <p>To Illustrate with an example:</p>
  
  <p>Start with 3 rows, EditText's all empty<br>
  In row 2, enter '5', '6'<br>
  Click 'More'->Adds an (empty) row on the end. Now 4 rows.<br>
  Delete last row->3 rows displayed, BUT 2nd AND 3rd rows now display '5', '6'->???????</p>
  
  <p>It looks like the relative position of EditText objects within the ListView is not stable after rebinding which is causing the problem. E.g. EditText object 'X' starts in position 3, then after a rebind it is in position 1 - but it still has a CustomTextWatcher attached to it referencing the data object in position 3. The other issue is the fact that addTextChangedListener() does not affect the TextWatchers already attached to the EditText. </p>
  
  <p>I'm pretty new to Android, so I'm not sure if there is a better approach to solve my problem. Any help is appreciated.</p>