title: Setting ListView item checked from Adapter
body: <p>I have a ListView which displays 2 kinds of items. One of these kinds contains CheckedTextView. As an adapter I'm using custom adapter extending ArrayAdapter with data structure containing information about checked/unchecked states inside. </p>
  
  <p>Some of the items are marked as selected (in my data structure) so of course I'd like the checkboxes to be marked when the ListView is created. I tried to do it on getView() method in adapter with CheckedTextView's setChecked() method but it doesn't work. I found information that it should be done on a ListView level with setItemChecked() and it does work but it doesn't make sense to me because to make it work I would have to loop all items in activity's onCreate() calling setItemChecked() for those selected. The list of items may be very long with only a few of them selected so it's a waste.</p>
  
  <p>Why calling setChecked() in getView() isn't working? Is there a better way of doing this (I'm an Android newbie).</p>
  
  <p>Below you have my checked item layout and the adapter.</p>
  
  <p>Layout:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@android:id/text1"
      android:layout_width="fill_parent"
      android:layout_height="?android:attr/listPreferredItemHeight"
      android:gravity="center_vertical"
      android:textAppearance="@style/listViewItemText"
      android:checkMark="?android:attr/listChoiceIndicatorMultiple"
      android:paddingLeft="6dp"
      android:paddingRight="6dp"
  /&gt;
  </code></pre>
  
  <p>Adapter:</p>
  
  <pre><code>package com.melog.re.droid.search;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import android.content.Context;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ArrayAdapter;
  import android.widget.CheckedTextView;
  import android.widget.TextView;
  
  import com.melog.re.droid.core.R;
  import com.melog.re.droid.search.MultiCriterionValue.MultiCriterionSingleValue;
  import com.melog.re.droid.search.MultiListAdapter.MultiChoiceItem;
  
  public class MultiListAdapter extends ArrayAdapter&lt;MultiChoiceItem&gt; {
      private static final int VIEW_TYPES_COUNT = 2;
  
      public static final int VIEW_TYPE_GROUP = 0;
      public static final int VIEW_TYPE_ITEM = 1;
  
      private LayoutInflater mInflater;
  
      public MultiListAdapter(Context context, int textViewResourceId, List&lt;MultiChoiceItem&gt; objects) {
          super(context, textViewResourceId, objects);
          mInflater = LayoutInflater.from(context);
      }
  
      @Override
      public int getItemViewType(int position) {
          MultiChoiceItem item = getItem(position);
          return (item.children.size() == 0) ? VIEW_TYPE_ITEM : VIEW_TYPE_GROUP;
      }
  
      @Override
      public int getViewTypeCount() {
          return VIEW_TYPES_COUNT;
      }
  
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
          // TODO: optymalizacja ViewHolder
          MultiChoiceItem item = getItem(position);
          int viewType = getItemViewType(position);
          switch (viewType) {
          case VIEW_TYPE_GROUP:
              if (convertView == null) {
                  convertView = mInflater.inflate(R.layout.multi_choice_group_item, parent, false);
              }
              TextView groupLabel = (TextView) convertView.findViewById(android.R.id.text1);
              groupLabel.setText(item.toString());
              break;
          case VIEW_TYPE_ITEM:
              if (convertView == null) {
                  convertView = mInflater.inflate(R.layout.multi_choice_child_item, parent, false);
              }
              CheckedTextView itemLabel = (CheckedTextView) convertView.findViewById(android.R.id.text1);
              itemLabel.setText(item.toString());
              itemLabel.setChecked(item.selected);
              break;
          }
  
          return convertView;
      }
  
      public static class MultiChoiceItem implements Parcelable {
          public static final int CONTENTS_DESCR = 1;
  
          public String label;
          public String value;
          public boolean selected = false;
          public ArrayList&lt;MultiChoiceItem&gt; children = new ArrayList&lt;MultiChoiceItem&gt;();
  
          public MultiChoiceItem(String l, String v, boolean sel) {
              label = l;
              value = v;
              selected = sel;
          }
          public MultiChoiceItem(MultiCriterionSingleValue v) {
              label = v.toString();
              value = v.value;
          }
          public MultiChoiceItem(Parcel in) {
              label = in.readString();
              value = in.readString();
              selected = (in.readInt() == 1);
          }
          @Override
          public String toString() {
              return label;
          }
          @Override
          public int describeContents() {
              return CONTENTS_DESCR;
          }
          @Override
          public void writeToParcel(Parcel dest, int flags) {
              dest.writeString(label);
              dest.writeString(value);
              dest.writeInt(selected ? 1 : 0);
          }
  
          public static final Parcelable.Creator&lt;MultiChoiceItem&gt; CREATOR = new Parcelable.Creator&lt;MultiChoiceItem&gt;() {
              public MultiChoiceItem createFromParcel(Parcel in) {
                  return new MultiChoiceItem(in);
              }
  
              public MultiChoiceItem[] newArray(int size) {
                  return new MultiChoiceItem[size];
              }
          };
  }
  }
  </code></pre>
  
  <p>And a piece of activity's onCreate()</p>
  
  <pre><code>...     
  mAdapter = new MultiListAdapter(this, R.id.head, mItems);
  setListAdapter(mAdapter);
  
  final ListView listView = getListView();
  listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
  listView.setItemsCanFocus(false);
  ...
  </code></pre>
  
  <p>Edit:</p>
  
  <p>Until finding a better solution I implemented the checking in the Activity:</p>
  
  <pre><code>...
  int len = mListView.getCount();
  for (int i = 0; i &lt; len; i++) {
      if (((MultiChoiceItem) mListView.getItemAtPosition(i)).selected) {
          mListView.setItemChecked(i, true);
      }
  }
  ...
  </code></pre>
  
  <p>I thought that performance will be the only potential problem but I found another one - much more serious. The list has text filter enabled (mListView.setTextFilterEnabled(true)). Here's the failure scenario:</p>
  
  <ol>
  <li>I'm opening new list</li>
  <li>Im checking let's say 2-nd item</li>
  <li>I start typing to filter some items</li>
  <li>when the filtering is done, the 2-nd item is still checked even though it's not the one I checked</li>
  </ol>
  
  <p>I assume that  setItemChecked() marks a fixed position on the list checked while I need something that will mark the Item held on ths position - keeping the state even when the position on the list changes.</p>
  
  <p>While performance issue could be (to some point) ignored - this new problem is really blocking me, so I would really appreciate any help with it.</p>