1

I want to try to get a list of food items from an API and update the AutoCompleteTextView based on this.

I've tried following the answer here but to no avail: https://stackoverflow.com/a/36799955/7429535

This is my code so far:

//Outside onCreate
List<String> apiFoods = new ArrayList<>();
//In onCreate
 AutoCompleteTextView autocomplete = (AutoCompleteTextView) findViewById(R.id.foodActv);
 final ArrayAdapter<String> autoAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, apiFoods);
 autocomplete.setAdapter(autoAdapter);

 autocomplete.addTextChangedListener(new TextWatcher() {
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {

     }

     @Override
     public void onTextChanged(CharSequence s, int start, int before, int count) {
         //retrieve data s
     }

     @Override
     public void afterTextChanged(Editable s) {
         retrieveData(s);
         autoAdapter.notifyDataSetChanged();
         Log.d("TAG", "foodsApi is " + apiFoods);
     }
});
//Below onCreate
private void retrieveData(Editable s)
{
    String text = s.toString();
    if(text.contains(" "))
    {
        text.replace(" ", "%20");
    }
    String url = "https://api.edamam.com/api/food-database/parser?ingr="+text+"&app_id=8ff4be18&app_key=f2bf020e6d3cf1a9989c2a2163fb720f";
    new AsyncHttpClient().get(url, new AsyncHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Header[] headers, byte[] responseBody)
        {
            try
            {
                JSONObject foodNames=new JSONObject(new String(responseBody));
                JSONArray jArray = foodNames.getJSONArray("hints");
                for(int i = 0; i < jArray.length(); i++)
                {
                    try
                    {
                        JSONObject hintItem = jArray.getJSONObject(i);
                        JSONObject foodItem = hintItem.getJSONObject("food");
                        String foodLabel = foodItem.getString("label");
                        apiFoods.add(foodLabel);
                    }
                    catch(JSONException e)
                    {

                    }
                }
            } catch (JSONException e)
            {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
            Toast.makeText(getApplicationContext(), "API call failed", Toast.LENGTH_SHORT).show();
        }
    });
}

You can see an example API response here: https://api.edamam.com/api/food-database/parser?ingr=red&app_id=8ff4be18&app_key=f2bf020e6d3cf1a9989c2a2163fb720f

Currently, this code IS inputting the correct food names into the apiFoods ArrayList but it is not showing me the options to select in app.

Kasım Özdemir
  • 5,414
  • 3
  • 18
  • 35
Daniel Lawton
  • 416
  • 3
  • 9
  • 30
  • Does this answer your question? [AutoCompleteTextView not showing suggestion](https://stackoverflow.com/questions/13456448/autocompletetextview-not-showing-suggestion) – Rajen Raiyarela Apr 12 '20 at 12:47
  • @RajenRaiyarela I'm afraid that didn't help. I tried putting after the .setAdapater but notice I also have the notifyDataSetChanged(); in the afterTextChanged override method. – Daniel Lawton Apr 12 '20 at 12:50
  • That `AsyncHttpClient` operation that you're doing in `retrieveData()` is asynchronous. Your code does not pause and wait there for the response, but continues immediately to return from that method, and then onto the `autoAdapter.notifyDataSetChanged()` call, at which point, `onSuccess()` has not run yet, so your `apiFoods` hasn't been updated. You'll need to do that `autoAdapter.notifyDataSetChanged()` call at the end of `onSuccess()`. – Mike M. Apr 12 '20 at 12:53
  • @DanielLawton Your notifyDataSetChanged() should come inside onSuccess method after your for loop wherein you values to apiFoods. – Rajen Raiyarela Apr 12 '20 at 12:53
  • @MikeM. I've changed my retrieve data method to take an ```ArrayAdapter``` and pass in my autoAdapter in the method call ```retrieveData(s, autoAdapter);``` I placed the ```autoAdapter.notifyDataSetChanged()``` at the end of the ```onSuccess()``` method but sadly nothing has changed. – Daniel Lawton Apr 12 '20 at 13:00
  • Oh, right, `AutoCompleteTextView`. It's been a while since I've used that, but I have a feeling that the constant updates of the dataset are fighting against its own built-in filtering. I'd have to look into that later, though, if I get a chance. – Mike M. Apr 12 '20 at 13:54

1 Answers1

2

kindly note that you are initializing your adatapter long before you make an api call, so I suggest that when your api returns data inside your public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) function, do reinitialise your adapter as below.

private void retrieveData(final AutoCompleteTextView s)
{
    String text = s.toString();
    if(text.contains(" "))
    {
        text.replace(" ", "%20");
    }
    String url = "https://api.edamam.com/api/food-database/parser?ingr="+text+"&app_id=8ff4be18&app_key=f2bf020e6d3cf1a9989c2a2163fb720f";
    new AsyncHttpClient().get(url, new AsyncHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Header[] headers, byte[] responseBody)
        {
            try
            {
                JSONObject foodNames=new JSONObject(new String(responseBody));
                JSONArray jArray = foodNames.getJSONArray("hints");
                for(int i = 0; i < jArray.length(); i++)
                {
                    try
                    {
                        JSONObject hintItem = jArray.getJSONObject(i);
                        JSONObject foodItem = hintItem.getJSONObject("food");
                        String foodLabel = foodItem.getString("label");
                        apiFoods.add(foodLabel);
                    }
                    catch(JSONException e)
                    {

                    }
                }

                autoAdapter = new ArrayAdapter<>(ActivityName.this, android.R.layout.simple_dropdown_item_1line, apiFoods);

 s.setAdapter(autoAdapter);

s.setThreshold(1);

        s.setAdapter(adapter);

            } catch (JSONException e)
            {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
            Toast.makeText(getApplicationContext(), "API call failed", Toast.LENGTH_SHORT).show();
        }
    });
}
yaddly
  • 340
  • 2
  • 14
  • I appreciate the help. I am getting an error though. When trying to do ```s.setAdapter(autoAdapter)``` I get ```Cannot resolve method 'setAdapter(android.widget.ArrayAdapter)``` – Daniel Lawton Apr 12 '20 at 13:16
  • I replaced ```autoAdapter = new ArrayAdapter<>(ActivityName.this, android.R.layout.simple_dropdown_item_1line, apiFoods); s.setAdapter(autoAdapter); s.setThreshold(1);``` with ```AutoCompleteTextView autocomplete = (AutoCompleteTextView) findViewById(R.id.foodActv); ArrayAdapter autoAdapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_dropdown_item_1line, apiFoods); autocomplete.setAdapter(autoAdapter);``` Now I am seeing some predictions, but only when I press backspace after typing something. – Daniel Lawton Apr 12 '20 at 13:37
  • 1
    Adding ```autocomplete.showDropDown();``` made this work properly after fixes above. Thanks! – Daniel Lawton Apr 12 '20 at 14:22
  • @DanielLawton, kindly accept the answer above if it was helpful, I would appreciate an upvote. – yaddly Apr 12 '20 at 18:58
  • @DanielLawton you're getting this error `Cannot resolve method 'setAdapter(android.widget.ArrayAdapter)` because you are passing an instance of `Editable` to `retrieveData(final Editable s)` function, simply change to method parameter type to `retrieveData(final AutoCompleteTextView s)` and the above code should work as is. You will also need to make a minor change to your method call from`retrieveData(s);` to `retrieveData(autocomplete);` – yaddly Apr 12 '20 at 19:50