title: Android Search Filter with custom listview, custom adapter and custom object
body: <p>I'm trying to implement a search filter for my code however, I'm having some problem at the moment. The error that I'm receiving is:</p>
  
  <blockquote>
    <p>ArrayList cannot be cast to CustomApapter</p>
  </blockquote>
  
  <p>I know that this error is happening because I am using List within my CustomAdapter instead of ArrayList. The problem is that I don't know how to fix it to get it to work properly. </p>
  
  <p><strong><em>CustomAdapter</em></strong></p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.List;
  
  import android.app.Activity;
  import android.content.Context;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ArrayAdapter;
  import android.widget.Filter;
  import android.widget.TextView;
  
  public class CustomAdapter extends ArrayAdapter&lt;Records&gt; {
  
      Context context;
      int layoutResourceId;
      List&lt;Records&gt; data;
  
      private Filter fRecords;
  
      public CustomAdapter(Context context, int layoutResourceId, List&lt;Records&gt; data) {
          super(context, layoutResourceId, data);
          // TODO Auto-generated constructor stub
          this.layoutResourceId = layoutResourceId;
          this.context = context;
          this.data = data;
      }
  
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
          // TODO Auto-generated method stub
  
          View row = convertView;
          DataHolder holder = null;
  
          if (row == null) {
              LayoutInflater inflater = ((Activity)context).getLayoutInflater();
              row = inflater.inflate(layoutResourceId, parent, false);
  
              holder = new DataHolder();
              holder.dataName = (TextView)row.findViewById(R.id.dataName);
              holder.dataType = (TextView)row.findViewById(R.id.dataType);
  
              row.setTag(holder);
          } else {
              holder = (DataHolder)row.getTag();
          }
  
          Records records = data.get(position);
          holder.dataName.setText(records.getName());
          holder.dataType.setText(records.getType());
  
          return row;
      }
  
      private class RecordFilter extends Filter {
  
          @Override
          protected FilterResults performFiltering(CharSequence constraint) {
              FilterResults results = new FilterResults();
  
              //Implement filter logic
              if (constraint == null || constraint.length() == 0) {
                  //No need for filter
                  results.values = data;
                  results.count = data.size();
              } else {
                  //Need Filter
                  List&lt;Records&gt; fRecords = new ArrayList&lt;Records&gt;();
  
                  for (Records s : data) {
                      if (s.getName().toUpperCase().contains(constraint.toString().toUpperCase())) {
                          fRecords.add(s);
                      }
                  }
  
                  results.values = fRecords;
                  results.count = fRecords.size();
              }
              return results;
          }
  
          @Override
          protected void publishResults(CharSequence constraint,
                  FilterResults results) {
              //inform the adapter about the new list
              if (results.count == 0) {
                  notifyDataSetInvalidated();
              } else {
                  data = (List&lt;Records&gt;) results.values;
                  notifyDataSetChanged();
              }
  
          }
  
      }
  
      @Override
      public Filter getFilter() {
          if (fRecords == null) {
              fRecords = new RecordFilter();
          }
  
          return fRecords;
      }
  
      static class DataHolder {
          TextView dataName;
          TextView dataType;
      }
  
  }
  </code></pre>
  
  <p><strong><em>DataLayout</em></strong></p>
  
  <pre><code>import java.util.List;
  
  import android.app.Activity;
  import android.content.Intent;
  import android.os.Bundle;
  import android.widget.ListView;
  import android.text.Editable;
  import android.text.TextWatcher;
  import android.view.View;
  import android.widget.AdapterView;
  import android.widget.AdapterView.OnItemClickListener;
  import android.widget.Button;
  import android.widget.EditText;
  
  public class DataLayout extends Activity {
      private RecordsDataSource datasource;
  
      Button btnDataCancel;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.data_layout);       
  
          datasource = new RecordsDataSource(this);
          datasource.open();
  
          final List&lt;Records&gt; values = datasource.getNameType();
  
          //use the SimpleCursorAdapter to show the
          //elements in a ListView
          //ArrayAdapter&lt;Records&gt; adapter = new ArrayAdapter&lt;Records&gt;(this, android.R.layout.simple_list_item_1, values);
          //setListAdapter(adapter);
  
  
          CustomAdapter adapter = new CustomAdapter(this, R.layout.data_layout_listview, values);
          final ListView listView1 = (ListView)findViewById(R.id.listView1);
  
          listView1.setAdapter(adapter);
  
  
          Button btnDataCancel = (Button)findViewById(R.id.btnDataCancel);
  
          //Cancel Button
          btnDataCancel.setOnClickListener(new View.OnClickListener() {
  
              public void onClick(View arg0) {
                  //Starting a new Intent
                  Intent goMain = new Intent(getApplicationContext(), MainActivity.class);
  
                  startActivity(goMain);
                  finish();
              }
          });
  
          //ListView onClick
          listView1.setOnItemClickListener(new OnItemClickListener() {
              public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position, long id) {
                  Object o = listView1.getItemAtPosition(position);
                  Records str =(Records)o;
  
                  Intent rData = new Intent(DataLayout.this, RecordView.class);
                  rData.putExtra("DataId", String.valueOf(str.getId()));
                  DataLayout.this.startActivity(rData);
                  //Toast.makeText(getBaseContext(), str.getName(), Toast.LENGTH_SHORT).show();
              }
          });
  
          //Filter Text
          EditText edtFilter = (EditText)findViewById(R.id.edtFilter);
  
          edtFilter.addTextChangedListener(new TextWatcher() {
  
              @Override
              public void afterTextChanged(Editable s) {
                  // TODO Auto-generated method stub
  
              }
  
              @Override
              public void beforeTextChanged(CharSequence s, int start, int count,
                      int after) {
                  // TODO Auto-generated method stub
  
              }
  
              @Override
              public void onTextChanged(CharSequence s, int start, int before,
                      int count) {
                  System.out.println("Text [" + s + "]");
                  ((CustomAdapter) values).getFilter().filter(s.toString());
  
              }
  
          });
      }
  
      @Override
      protected void onResume() {
          datasource.open();
          super.onResume();
      }
  
      @Override
      protected void onPause() {
          datasource.close();
          super.onPause();
      }
  }
  </code></pre>
  
  <p>Edit1:
  @alexei burmistrov
  Thank you for your help, it now throws a different error. Below is the log:</p>
  
  <pre><code>05-20 22:54:39.275: E/AndroidRuntime(526): FATAL EXCEPTION: main
  05-20 22:54:39.275: E/AndroidRuntime(526): java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3
  05-20 22:54:39.275: E/AndroidRuntime(526):  at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at java.util.ArrayList.get(ArrayList.java:308)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at com.pbear.drillmaster.CustomAdapter.getView(CustomAdapter.java:69)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.AbsListView.obtainView(AbsListView.java:1949)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.ListView.measureHeightOfChildren(ListView.java:1228)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.ListView.onMeasure(ListView.java:1139)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.View.measure(View.java:10828)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1284)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.LinearLayout.measureVertical(LinearLayout.java:613)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.LinearLayout.onMeasure(LinearLayout.java:519)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.View.measure(View.java:10828)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:267)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.View.measure(View.java:10828)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1284)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.LinearLayout.measureVertical(LinearLayout.java:613)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.LinearLayout.onMeasure(LinearLayout.java:519)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.View.measure(View.java:10828)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:267)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:1889)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.View.measure(View.java:10828)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.ViewRoot.performTraversals(ViewRoot.java:938)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.view.ViewRoot.handleMessage(ViewRoot.java:2040)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.os.Handler.dispatchMessage(Handler.java:99)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.os.Looper.loop(Looper.java:132)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at android.app.ActivityThread.main(ActivityThread.java:4123)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at java.lang.reflect.Method.invokeNative(Native Method)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at java.lang.reflect.Method.invoke(Method.java:491)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
  05-20 22:54:39.275: E/AndroidRuntime(526):  at dalvik.system.NativeStart.main(Native Method)
  </code></pre>
  
  <p>Edit2:
  Thanks to alexei burmistrov for clearing up a lot of the concept with filtering. I have finally got it working.</p>