由远程 API 填充的 AutoCompleteTextView 给出异常 IndexOutOfBoundsException OnItemClickListener

AutoCompleteTextView populated by remote API gives exception IndexOutOfBoundsException OnItemClickListener

所以我想实现一个动态的 AutoCompleteTextView,它将给出要在 AutoCompleteTextView 的下拉列表中填充的列表。

下面是我写的文件和代码。

addLocationEdit = (AutoCompleteTextView) footerView.findViewById(R.id.add_locations_list_edit);

    addLocationEdit.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) {
            new ForLocations().execute(s);
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });

    addLocationEdit.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            Log.e(Constants.TAG, "LOCATIONS LIST SIZE: " + locationList.size());

            list.add(new AddLocationsBean(locationList.get(position).getId(), locationList.get(position).getName(), locationList.get(position).getDistrict(), locationList.get(position).getState()));
            adapter.notifyDataSetChanged();
            addLocationEdit.setText("");
        }
    });

下面是我使用的 AsyncTask:

class ForLocations extends AsyncTask<CharSequence, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        locationList = new ArrayList<>();
    }

    @Override
    protected Void doInBackground(CharSequence... params) {

        try {

            CharSequence param = params[0];

            URL url = new URL(Api.LOCATION_URL + "q=" + param);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");

            inputStream = conn.getErrorStream();
            if (inputStream == null) {
                inputStream = conn.getInputStream();
            }

            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(inputStream), 1000);
            stringBuilder = new StringBuilder();
            stringBuilder.append(reader.readLine() + "\n");

            String line = "0";
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line + "\n");
            }

            inputStream.close();
            locationResponse = stringBuilder.toString();
        } catch (Exception e) {
            Log.e("LOCATION ERROR: ", "LOCATION ERROR: " + e);
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        try {

            // PARSE JSON

            locationAdapter = new LocationAutoCompleteAdapter(MainActivity.this, locationList);
            addLocationEdit.setAdapter(locationAdapter);
            locationAdapter.notifyDataSetChanged();

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

以下是我正在使用的适配器:

public class LocationAutoCompleteAdapter extends ArrayAdapter<LocationBean> {

Context context;
LayoutInflater inflater;
ArrayList<LocationBean> suggestions, list, tempList;

InputStream inputStream;
StringBuilder stringBuilder;
String locationResponse;

Filter nameFilter = new Filter() {
    @Override
    public CharSequence convertResultToString(Object resultValue) {
        String str = ((LocationBean) resultValue).getName();
        return str;
    }

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        if (constraint != null) {
            suggestions.clear();
            for (LocationBean locationBean : tempList) {
                if (locationBean.getName().toLowerCase().contains(constraint.toString().toLowerCase()) || locationBean.getState().toLowerCase().contains(constraint.toString().toLowerCase()) || locationBean.getDistrict().toLowerCase().contains(constraint.toString().toLowerCase())) {
                    suggestions.add(locationBean);
                }
            }
            FilterResults filterResults = new FilterResults();
            filterResults.values = suggestions;
            filterResults.count = suggestions.size();
            return filterResults;
        } else {
            return new FilterResults();
        }
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        List<LocationBean> filterList = (ArrayList<LocationBean>) results.values;
        if (results != null && results.count > 0) {
            clear();
            for (LocationBean locationBean : filterList) {
                add(locationBean);
                notifyDataSetChanged();
            }
        }
    }
};

public LocationAutoCompleteAdapter(Context context, ArrayList<LocationBean> list) {
    super(context, R.layout.location_autocomplete_list_item, list);
    this.context = context;
    this.list = list;
    this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    tempList = new ArrayList<LocationBean>(list); // this makes the difference.
    suggestions = new ArrayList<LocationBean>();
}

@Override
public LocationBean getItem(int position) {
    return tempList.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        holder = new ViewHolder();

        convertView = inflater.inflate(R.layout.location_autocomplete_list_item, parent, false);

        holder.name = (TextView) convertView.findViewById(R.id.autcom_name);
        holder.state = (TextView) convertView.findViewById(R.id.autcom_state);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    if (list.get(position).getState().isEmpty()) {
        holder.state.setVisibility(View.GONE);
    } else {
        holder.state.setVisibility(View.VISIBLE);
    }
    holder.name.setText(list.get(position).getName());
    holder.state.setText(list.get(position).getState());

    return convertView;
}

@Override
public Filter getFilter() {
    return nameFilter;
}

class ViewHolder {
    TextView name, state;
}}

当我点击列表项时出现以下错误:

FATAL EXCEPTION: mainProcess: varun.com.dynamicautocompletetextview, PID: 27492 ava.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) at java.util.ArrayList.get(ArrayList.java:308) at varun.com.dynamicautocompletetextview.MainActivity.onItemClick(MainActivity.java:110) at android.widget.AutoCompleteTextView.performCompletion(AutoCompleteTextView.java:906) at android.widget.AutoCompleteTextView.-wrap1(AutoCompleteTextView.java) at android.widget.AutoCompleteTextView$DropDownItemClickListener.onItemClick(AutoCompleteTextView.java:1202) at android.widget.AdapterView.performItemClick(AdapterView.java:310) at android.widget.AbsListView.performItemClick(AbsListView.java:1145) at android.widget.AbsListView$PerformClick.run(AbsListView.java:3066) at android.widget.AbsListView.run(AbsListView.java:3903) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5466) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

这是一个 IndexOutOfBoundsException,当我单击列表项时发生。

请提出可能的原因以及解决方法。

随时提出通过网络 service/API 调用实现 AutoCompleteTextView 填充的任何新方法。

谢谢。

编辑: 正在 AutoCompleteTextView 中填充数据。我已经登录并检查过,我可以在下拉列表中看到数据本身。

所以我找到了解决方案,就在这里。

  1. 不要覆盖 getItemgetCount(如果您使用的是 ArrayAdapter)。
  2. 而不是使用 list.get(position) 使用 parent.getItemAtPosition(position)
  3. 如下:
LocationBean bean = (LocationBean) parent.getItemAtPosition(position);
list.add(new AddLocationsBean(bean.getId(), bean.getName(), bean.getDistrict(), bean.getState()));
adapter.notifyDataSetChanged();
addLocationEdit.setText("");

谢谢。