2

I have an adapter that starts an async task to query an API. I implemented an interface in order to get a return value back from onPostExecute, and override the interface method in the adapter, following the example listed here: https://stackoverflow.com/a/12575319/5605646. The original code is taken from https://stackoverflow.com/a/33428678/5605646, but I want to use asyncTask for querying the API.

Since the return statement belongs to the interface overriden method, I don't know how to pass that returned value to another method in the adapter.

In the adapter class, DataBufferUtils.freezeAndClose(autocompletePredictions) returns the correct value, but what's being passed back to mResultList (inside new Filter()) is null, because getAutocomplete keeps going all the way until the return null line.

Does anyone know how I can pass the value from DataBufferUtils.freezeAndClose(autocompletePredictions) to mResultList?

Adapter

public class PlaceAutocompleteAdapter extends  ArrayAdapter<AutocompletePrediction> implements Filterable
{
    private static final String TAG = "PlaceAutocompleteAdapter";
    private static final CharacterStyle STYLE_BOLD = new    StyleSpan(Typeface.BOLD);
    private ArrayList<AutocompletePrediction> mResultList;
    private GoogleApiClient mGoogleApiClient;
    private LatLngBounds mBounds;
    private AutocompleteFilter mPlaceFilter;

public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient,LatLngBounds bounds, AutocompleteFilter filter){

    super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
    mGoogleApiClient = googleApiClient;
    mBounds = bounds;
    mPlaceFilter = filter;
}

@Override
public int getCount(){
    return mResultList.size();
}

@Override
public AutocompletePrediction getItem(int position){
    return mResultList.get(position);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = super.getView(position, convertView, parent);
    AutocompletePrediction item = getItem(position);
    TextView textView1 = (TextView) row.findViewById(android.R.id.text1);
    TextView textView2 = (TextView) row.findViewById(android.R.id.text2);
    textView1.setText(item.getPrimaryText(STYLE_BOLD));
    textView2.setText(item.getSecondaryText(STYLE_BOLD));

    return row;
}

// returns the filter for the current set of autocomplete results
@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            //skip the autocomplete query if no constraints are given
            if (constraint != null) {

                // query the autocomplete API for the search string
                mResultList = getAutocomplete(constraint);

                if (mResultList != null) {

                    //the API successfully returned results
                    results.values = mResultList;
                    results.count = mResultList.size();

                }
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                Log.i("notifyDataSetChanged","results are not null");
                // The API returned at least one result, update the data.
                notifyDataSetChanged();
            } else {
               Log.i("notifyDataSetInvalid", "results are null");
                // The API did not return any results, invalidate the data set.
                notifyDataSetInvalidated();
            }
        }

        @Override
        public CharSequence convertResultToString(Object resultValue) {
            // override this method to display a readable result in the AutocompleteTextView
            // when clicked.
            if (resultValue instanceof AutocompletePrediction) {
                return ((AutocompletePrediction) resultValue).getFullText(null);
            } else {
                return super.convertResultToString(resultValue);
            }
        }
    };
}

        public ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {

            if (mGoogleApiClient.isConnected()) {

                MyTaskParams params = new MyTaskParams(constraint, mGoogleApiClient, mBounds, mPlaceFilter);
                updateSuggestionAsync myTask = new updateSuggestionAsync(new AsyncResponse(){

                    @Override
                    public ArrayList<AutocompletePrediction> processFinish(AutocompletePredictionBuffer autocompletePredictions){

                        // Confirm that the query completed successfully, otherwise return null
                        final com.google.android.gms.common.api.Status status = autocompletePredictions.getStatus();
                        if (!status.isSuccess()) {
                            Log.i("Error contacting API","Error contacting API");
                            Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
                                    Toast.LENGTH_SHORT).show();
                            autocompletePredictions.release();
                            return null;
                        }

                        // Freeze the results immutable representation that can be stored safely.
                        return  DataBufferUtils.freezeAndClose(autocompletePredictions);
                    }
                });
                myTask.execute(params);

            }
           return null;
        }
   }

AsyncTask

public class updateSuggestionAsync extends  AsyncTask<MyTaskParams,Void,AutocompletePredictionBuffer>{

   public AsyncResponse delegate = null;

   public updateSuggestionAsync (AsyncResponse delegate){
       this.delegate = delegate;
   }

    @Override
    protected AutocompletePredictionBuffer  doInBackground(MyTaskParams...params){

        CharSequence constraint = params[0].constraint;
        GoogleApiClient mGoogleApiClient = params[0].mGoogleApiClient;
        LatLngBounds mBounds = params[0].mBounds;
        AutocompleteFilter mPlaceFilter = params[0].mPlaceFilter;

        PendingResult<AutocompletePredictionBuffer> results =
        Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, constraint.toString(),mBounds,mPlaceFilter);

        return results.await(60, TimeUnit.SECONDS);
}

    @Override
    protected void onPostExecute(AutocompletePredictionBuffer result){
            delegate.processFinish(result);
}
}

Interface

public interface AsyncResponse {
    public ArrayList<AutocompletePrediction> processFinish((AutocompletePredictionBuffer output);
 }
Community
  • 1
  • 1

1 Answers1

0

Solved it by doing the following:

  1. Removed constructor from AsyncTask class
  2. Called getAutocomplete(constraint), without setting the return value as mResultList
  3. Override processFinish as its own method in Adapter class, not nested within another method.
  4. Set mResultList = DataBufferUtils.freezeAndClose(autocompletePredictions) within processFinish. Since mResultList is a global variable, when it is then used in a different method it already has the right results in it.

New Adapter:

public class PlaceAutocompleteAdapter extends ArrayAdapter<AutocompletePrediction> implements Filterable,AsyncResponse
{

private static final String TAG = "PlaceAutocompleteAdapter";
private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD);

// Current results returned by this adapter.
private ArrayList<AutocompletePrediction> mResultList;

// Handles autocomplete requests.
private GoogleApiClient mGoogleApiClient;

// The bounds used for Places Geo Data autocomplete API requests.
private LatLngBounds mBounds;

// The autocomplete filter used to restrict queries to a specific set of place types.
private AutocompleteFilter mPlaceFilter;

//constructor
public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient,
                                LatLngBounds bounds, AutocompleteFilter filter){

super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
    mGoogleApiClient = googleApiClient;
    mBounds = bounds;
    mPlaceFilter = filter;
}

 //returns the number of results received in the last autocomplete query
@Override
public int getCount(){
    return mResultList.size();
}

// returns an item from the last autocomplete query
@Override
public AutocompletePrediction getItem(int position) {
    return mResultList.get(position);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View row = super.getView(position, convertView, parent);

    // sets the primary and secondary text for a row.
    // note that getPrimaryText() and getSecondaryText() return a CharSequence that may
    // contain styling based on the given CharacterStyle

    AutocompletePrediction item = getItem(position);

    TextView textView1 = (TextView) row.findViewById(android.R.id.text1);
    TextView textView2 = (TextView) row.findViewById(android.R.id.text2);
    textView1.setText(item.getPrimaryText(STYLE_BOLD));
    textView2.setText(item.getSecondaryText(STYLE_BOLD));

    return row;
}

// returns the filter for the current set of autocomplete results
@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            //skip the autocomplete query if no constraints are given
            if (constraint != null) {

                getAutocomplete(constraint);

                if (mResultList != null) {
                    //the API successfully returned results
                    results.values = mResultList;
                    results.count = mResultList.size();
                }
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                Log.i("notifyDataSetChanged","results are not null");
                // The API returned at least one result, update the data.
                notifyDataSetChanged();
            } else {
               Log.i("notifyDataSetInvalid", "results are null");
                // The API did not return any results, invalidate the data set.
                notifyDataSetInvalidated();
            }
        }

        @Override
        public CharSequence convertResultToString(Object resultValue) {
            // override this method to display a readable result in the AutocompleteTextView
            // when clicked.
            if (resultValue instanceof AutocompletePrediction) {
                return ((AutocompletePrediction) resultValue).getFullText(null);
            } else {
                return super.convertResultToString(resultValue);
            }
        }
    };
}

        public void  getAutocomplete(CharSequence constraint) {

            if (mGoogleApiClient.isConnected()) {
                MyTaskParams params = new MyTaskParams(constraint, mGoogleApiClient, mBounds, mPlaceFilter);

                updateSuggestionAsync myTask = new updateSuggestionAsync();
                myTask.delegate=this;
                myTask.execute(params);
            }
        }

@Override
public ArrayList<AutocompletePrediction> processFinish(AutocompletePredictionBuffer autocompletePredictions){
    Log.i("made it processFinish","made it processFinish");
    // Confirm that the query completed successfully, otherwise return null
    final com.google.android.gms.common.api.Status status = autocompletePredictions.getStatus();
    if (!status.isSuccess()) {
        Log.i("Error contacting API","Error contacting API");
        Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
                Toast.LENGTH_SHORT).show();
        autocompletePredictions.release();
        return null;
    }
    mResultList = DataBufferUtils.freezeAndClose(autocompletePredictions);
    // Freeze the results immutable representation that can be stored safely.
    return  mResultList;
}