Dynamically updating an AutoCompleteTextView adapter

jaybee picture jaybee · Nov 11, 2011 · Viewed 44k times · Source

I want to periodically change the suggestions given by an AutoCompleteTextview by getting the list from a RESTful web service, and can't get it working smoothly. I set up a hard-coded list of suggestions to make sure it's working:

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, new String[] {"Hi", "Ho"});
speciesName.setAdapter(adapter);//my autocomplete tv

I have got a TextWatcher on the textview and when the text changes that launches a non-blocking call to get a new list of suggestions -- this part which gets a new list is working fine. Then I want to reset the adapter, like so:

public void setOptionsAndUpdate(String[] options) {
    Log.d(TAG, "setting options");
    //speciesName.setAdapter((ArrayAdapter<String>)null);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, options);
    speciesName.setAdapter(adapter);
}

This method is called, but doesn't work -- the list of suggestions either disappears or the displayed suggestions remain unchanged despite the call to setAdapter.

Is this even the right approach? I looked at SimpleCursorAdapter but couldn't see how to register my web service as a content provider. (It's of the form http://www.blah.com/query?term=XX, where the XX is the input from my app, and the response is a JSON Array of strings.)

Answer

GLee picture GLee · Oct 29, 2013

I didn't have any luck using adapter.notifyDataSetChanged() when dynamically adding and changing the data in the adapter. In my situation, I was hitting an external api asynchronously and getting a list of completion data periodically.

This code clears the adapter, and adds the new data as you'd expect. However, I had to call the getFilter().Filter method to force the data to show. Also, I had to explicitly filter based on the current text in the AutocompleteTextView because my api call was asynchronous.

adapter.clear();
for (Map<String, String> map : completions) {
     adapter.add(map.get("name"));
}

//Force the adapter to filter itself, necessary to show new data.
//Filter based on the current text because api call is asynchronous. 
adapter.getFilter().filter(autocompleteTextView.getText(), null);