9

I add TextChangedListener to AutocompleteTextView. In TextChangedListener's afterTextChanged() I invoke AsyncTask which loads data from web (loading all the data when activity starts is not an option because lists can be pretty large, so it becomes just waste of traffic). AsyncTask's onPostExecute() looks like that (I use ArrayAdapter):

    @Override
    protected void onPostExecute(ArrayList<Subregion> result)
    {
        super.onPostExecute(result);
        if (result != null)
        {
            adapter.clear();
            for (Iterator<Subregion> iterator = result.iterator(); iterator.hasNext();)
            {
                Subregion subregion = iterator.next();
                adapter.add(subregion);
            }
            adapter.notifyDataSetChanged();
            autocompleteTextView.showDropDown();
        }
    }

Subregion is my custom object with overriden toString(). I want my program to start loading data when user starts typing and show results at once they are received and parsed.

My problem:

autocompleteTextView.showDropDown() has no effect. onPostExecute() receives correct list of data, they are added to adapter, but showDropDown() doesn't show the dropdown. What's the matter?

Sufian
  • 6,405
  • 16
  • 66
  • 120
Eugene Chumak
  • 3,272
  • 7
  • 34
  • 52

4 Answers4

19

I am doing the exact same thing, and I just achieved this functionality. Instead of clearing the adapter and building it individually, set the adapter as below(I do this in a function which is called in the onPostExecute);

//suggestions is a string array of suggestions.
suggestAdapter = new ArrayAdapter<String>(this, R.layout.suggestions, suggestions);
//The autocomplete view 
suggestions.setAdapter(this.suggestAdapter);
suggestAdapter.notifyDataSetChanged();

You do not need to explicitly call showdropdown, the autocomplete view is automatically updated when the adapter notifies it that data has been changed.

You also can call

adapter.setNotifyOnChange(true)

which makes it unnecessary to call

adapter.notifyDatasetChanged()

See setNotifyOnChange Hope I could be of help.

Awemo
  • 875
  • 1
  • 12
  • 25
6

I also faced this issue. My completion threshold was 2. When 2 chars are typed, I was fetching data from server and had filled in array adapter but autoRailwayFrom.showDropDown(); does not show drop down...

I just write on line and it works...

autoRailwayFrom.setText(autoRailwayFrom.getText());
adapterFrom.notifyDataSetChanged();
autoRailwayFrom.showDropDown();
Bhavesh Hirpara
  • 22,255
  • 15
  • 63
  • 104
  • 1
    Rewriting the text definitely helped me, it caused the whole process to restart on my onResponse. Thank you so much! – upisdown Oct 20 '13 at 11:56
  • 1
    So issue with this is it moves the cursor to the start of the EditText view – kassim Mar 01 '15 at 16:43
1

This question has been answered but I believe that not in a good way - key for all is the filterable interface. Here you have working example of adapter, basing on BaseAdapter. Missing part here is communication (I used Retrofit):

public class UsersAutoAdapter extends BaseAdapter implements Filterable
{
    {
        DaggerGraphManager.INSTANCE.inject(this);
    }

    @Inject
    CommunicationManager mCommunicationManager;

    private FindUserResponse mFindUserResponse;

    @Override
    public int getCount()
    {
        if (mFindUserResponse != null && mFindUserResponse.mUsers != null)
        {
            return mFindUserResponse.mUsers.size();
        }

        return 0;
    }

    @Override
    public Object getItem(int i)
    {
        return mFindUserResponse.mUsers.get(i);
    }

    @Override
    public long getItemId(int i)
    {
        return i;
    }

    @Override
    public View getView(int i, View pView, ViewGroup pViewGroup)
    {
        if (pView == null)
        {
            LayoutInflater inflater = LayoutInflater.from(pViewGroup.getContext());
            pView = inflater.inflate(R.layout.ac_item_user, pViewGroup, false);
        }
        TextView textViewUserName = (TextView) pView.findViewById(R.id.text_view_user_name);
        textViewUserName.setText(mFindUserResponse.mUsers.get(i).mUserName);


        return pView;
    }

    @Override
    public Filter getFilter()
    {
        return new Filter()
        {
            //this method is called async (not from UI thread!) so making network request is possible here
            @Override
            protected FilterResults performFiltering(CharSequence pCharSequence)
            {

                if (pCharSequence != null && pCharSequence.length() >= 3)
                {
                    FindUserResponse users = mCommunicationManager.findUsersSync(pCharSequence.toString());

                    FilterResults results = new FilterResults();

                    results.values = users;
                    results.count = users.mUsers.size();

                    return results;
                }
                return null;
            }

            //this is UI thread called method (just after performFiltering returns it's results
            @Override
            protected void publishResults(CharSequence pCharSequence, FilterResults pFilterResults)
            {
                if (pFilterResults != null)
                {
                    mFindUserResponse = (FindUserResponse) pFilterResults.values;
                    notifyDataSetInvalidated();
                }
            }
        };
    }
}
piotrpo
  • 12,398
  • 7
  • 42
  • 58
0

Faced this problem with Retroft api call. Solved by keeping below code inside onResponse method of Retrofit. Do not need to initialize adapter inside onCreate method. My code was like below:

productListAdapter = new ArrayAdapter<>(getApplicationContext(), 
android.R.layout.simple_dropdown_item_1line, productList);

autoCompleteTextViewProductSearch.setAdapter(productListAdapter);
  productListAdapter.setNotifyOnChange(true);
  productListAdapter.notifyDataSetChanged();
  autoCompleteTextViewProductSearch.showDropDown();
Touhid
  • 1,556
  • 18
  • 18