For my AutoCompleteTextView
I need to fetch the data from a webservice. As it can take a little time I do not want UI thread to be not responsive, so I need somehow
With the approach above, i also had those problems when typing very fast. I guess it´s because the filtering of the results is done asynchronously by the filter class, so there can be problems when modifying the ArrayList of the Adapter in the ui thread while filtering is done.
http://developer.android.com/reference/android/widget/Filter.html
However with following approach everything worked fine.
public class MyActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyAdapter myAdapter = new MyAdapter(this, android.R.layout.simple_dropdown_item_1line);
AutoCompleteTextView acTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
acTextView.setAdapter(myAdapter);
}
}
public class MyAdapter extends ArrayAdapter {
private Filter mFilter;
private List mSubData = new ArrayList();
static int counter=0;
public MyAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
setNotifyOnChange(false);
mFilter = new Filter() {
private int c = ++counter;
private List mData = new ArrayList();
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// This method is called in a worker thread
mData.clear();
FilterResults filterResults = new FilterResults();
if(constraint != null) {
try {
// Here is the method (synchronous) that fetches the data
// from the server
URL url = new URL("...");
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
while ((line = rd.readLine()) != null) {
mData.add(new MyObject(line));
}
}
catch(Exception e) {
}
filterResults.values = mData;
filterResults.count = mData.size();
}
return filterResults;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence contraint, FilterResults results) {
if(c == counter) {
mSubData.clear();
if(results != null && results.count > 0) {
ArrayList objects = (ArrayList)results.values;
for (MyObject v : objects)
mSubData.add(v);
notifyDataSetChanged();
}
else {
notifyDataSetInvalidated();
}
}
}
};
}
@Override
public int getCount() {
return mSubData.size();
}
@Override
public MyObject getItem(int index) {
return mSubData.get(index);
}
@Override
public Filter getFilter() {
return mFilter;
}
}