Question

I am new to Android and experimenting with AutoCompleteTextView and different adapters. Having gotten it working with an ArrayAdapter (discussed here) I am now trying the same using a chain of two AsyncTasks. I have seen a couple examples of this approach elsewhere and I think it is tidier than attempting to syncronise data between threads. it also allows me to keep a K,V hashmap of each item so hopefully I can pull the item ID when clicking on a suggestion for the next stage of this application.

Under this approach, I am again struggling to get the View to update with suggestions. Nothing appears at all apart from what I type into the Edit box. Is this a timing issue between the UI thread and the AsyncTask chain? or perhaps I a mistake in the adapter/view binding?

Note: I have already tried with the autoComplete.setAdapter(adapter); being applied in the ParserTask onPostExecute() method. That didn't work either.

public class MainActivity extends Activity {
    public String TAG = new String("MAINACTIVITY");
    public CustomAutoCompleteView autoComplete;
    public InputStream inputStream;
    private String serviceURL = new String("http://www.autocompare.co.uk/search.php?q=");
    public QueryTask queryTask;
    public ParserTask parserTask;
    public SimpleAdapter adapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        autoComplete = (CustomAutoCompleteView) findViewById(R.id.autocomparesayt);
        autoComplete.setHint(R.string.search_hint);
        autoComplete.setThreshold(1);
        autoComplete.setAdapter(adapter);

        autoComplete.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(final CharSequence s, int start, int before, int count) {
                int queryThreshold = 3;
                if (s.length() != 2 && (s.length() - 1) % queryThreshold != 0) {
                    return;
                }

                queryTask = new QueryTask();
                queryTask.execute(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) { }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
       });
    }

    private class QueryTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... vehicle) {
            // Go fetch data from webservice
            // this bit works fine
            return(data);
        }

        @Override
        protected void onPostExecute(String result) {
            Log.d(TAG, "now entered parser task");
            super.onPostExecute(result);
            parserTask = new ParserTask();
            parserTask.execute(result);
        }
    }

    private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> {
        @Override
        protected List<HashMap<String, String>> doInBackground(String... jsonData) {
            List<HashMap<String, String>> vehicles = null;
            VehicleJSONParser vehicleJsonParser = new VehicleJSONParser();

            // parse JSON string and load data into vehicles
            // this bit works fine too

            return vehicles;
        }

        @Override
        protected void onPostExecute(List<HashMap<String, String>> result) {
            String[] from = {"name"};
            int[] to = new int[] { android.R.id.text1 };

            //  Attempt to set up adapter with data bubbled up from parserTask execution
            //  THIS BIT LOGS NO ERRORS, BUT AUTOCOMPLETETEXTVIEW REMAINS UNCHANGED
            adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1,
           from, to);
            adapter.notifyDataSetChanged();
        }
    }
}
Was it helpful?

Solution

Ok - sounds unbelievable, but it seems that moving the setAdapter() method back down to postExecute and keeping notifyDataSetChanged() in place, the darn thing is working!

(Next step is to figure out AutoCompleteTextView click events probably using intents/bundles/fragments.. wheee!)

Here is the final working code:

public class MainActivity extends Activity {
    public String TAG = new String("MAINACTIVITY");
    public CustomAutoCompleteView autoComplete;
    public InputStream inputStream;
    private String serviceURL = new String("http://www.blabla.co.uk/search.php?q=");
    public QueryTask queryTask;
    public ParserTask parserTask;
    public SimpleAdapter adapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        autoComplete = (CustomAutoCompleteView) findViewById(R.id.autocomparesayt);
        autoComplete.setHint(R.string.search_hint);
        autoComplete.setThreshold(1);

        autoComplete.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(final CharSequence s, int start, int before, int count) {
                int queryThreshold = 3;
                if (s.length() != 2 && (s.length() - 1) % queryThreshold != 0) {
                    return;
                }

                queryTask = new QueryTask();
                queryTask.execute(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) { }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
       });
    }

    private class QueryTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... vehicle) {
            // Go fetch data from webservice
            // this bit works fine
            return(data);
        }

        @Override
        protected void onPostExecute(String result) {
            Log.d(TAG, "now entered parser task");
            super.onPostExecute(result);
            parserTask = new ParserTask();
            parserTask.execute(result);
        }
    }

    private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> {
        @Override
        protected List<HashMap<String, String>> doInBackground(String... jsonData) {
            List<HashMap<String, String>> vehicles = null;
            VehicleJSONParser vehicleJsonParser = new VehicleJSONParser();

            // parse JSON string and load data into vehicles
            // this bit works fine too

            return vehicles;
        }

        @Override
        protected void onPostExecute(List<HashMap<String, String>> result) {
            String[] from = {"name"};
            int[] to = new int[] { android.R.id.text1 };

            adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1,
           from, to);
           autoComplete.setAdapter(adapter);
           adapter.notifyDataSetChanged();
        }
    }
} 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top