listview adapter click handled by wrong object when notifyDataSetChanged is called frequently and view inflated from layout
<p>I have an Android ListView that is frequently updated. When I click on an item in the list, some subset of the time the wrong object gets the click event. This occurs even when the update does not change the list.</p>

<p>Am I just coding this wrong, or is there a race condition in event handling through the view hierarchy?</p>

<p>The ListView uses an adapter that extends BaseAdapter, and its getView() method looks like the following. But the problem only appears when USE_LAYOUT=true.</p>

<pre><code>@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    View view;
    TextView textView;
    ViewHolder viewHolder;

    if (convertView == null) {
        if (USE_LAYOUT) {
            view = context.getLayoutInflater().inflate(R.layout.row, parent, false);
            textView = (TextView) view.findViewById(R.id.rowTextView);
        } else {
            view = new TextView(context);
            textView = (TextView) view;
        }
        viewHolder = new ViewHolder();
        viewHolder.textView = textView;
        view.setTag(viewHolder);
    } else {
        view = convertView;
        viewHolder = (ViewHolder) view.getTag();
        textView = viewHolder.textView;
    }

    final String item = getItem(position);
    textView.setText(position + " " + item);
    textView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("Adapter", position + " " + item);
        }
    });

    return view;
}
</code></pre>

<p>So in terms of the code above, the activity displays a list view showing "1 item1", "2 item2", "3 item3", etc. If I click on, say item3, some percentage of the time, the log will show "21 item21".</p>

<p>A couple of other points about the code:</p>

<ul>
<li>The item is just a String, the adapter maintains a <code>List&lt;String&gt;</code>, <code>getItem()</code> just calls <code>items.get(index)</code>, and <code>setItems()</code> sets the list and calls <code>notifyDataSetChanged()</code>.</li>
<li>The problem occurs if the list is not changed. I.e., the timer calls <code>setItems(new ArrayList&lt;String&gt;(getItems())</code>.</li>
<li><code>setItems()</code> is called from the UI thread via <code>runOnUiThread()</code>.</li>
<li>The timer goes off every 500ms or so, but the problem occurs with other frequencies.</li>
<li>The row layout is simply a TextView inside a LinearLayout.</li>
</ul>

<p>I have observed that when views are recycled through getView, they are recycled in reverse order. In other words, when<code>notifyDataSetChanged()</code> is called and the list has not scrolled, the first item is recycled with the last item, the second item is recycled with the second to last item, etc. Hence my suspicion of a race condition. Also, I observe it on 2.1 and 2.3, but not 4.0 (although I'm not sure it <em>never</em> occurs there).</p>
