杀死在perfromFilter中为Dynamic AutoCompleteTextView调用的AsyncTask

时间:2016-07-19 14:58:59

标签: java android android-asynctask autocompletetextview android-filter

我在Android中创建了一个动态AutoCompleteTextView。它有以下组件。

  1. 使用我的自定义POJO的ArrayAdapter。
  2. 适配器实现Filterable。
  3. 此过滤器调用AsyncTask,根据所获得的字符或约束获取所有数据。
  4. 获取所有数据后,AsyncTask解析数据,然后将列表返回到过滤器以供发布。
  5. 方案: 现在当我开始输入AutoCompleteTextView时,在输入第一个字符后,它会启动异步调用。然后,当我开始输入更多字符时,它会再次为每个字符调用异步,并通过过滤器发布结果。

    问题: 问题是,当为第一个字符调用第一个AsyncTask时,结果列表将在AutoCompleteTextView的下拉列表中发布,而我仍在键入TextView。然后我必须等待发布最新列表,这需要花费很多时间,因为每个字符都是异步执行。

    代码: 下面是我正在使用的适配器。

    typedef int l;
    mydecltype(l) x; // int x;
    mydecltype(x) y; // int y;
    

    我的想法:我认为在发布结果之前杀死正在运行的AsyncTask将是一个很好的解决方案。但我无法这样做。如果您有更好的解决方案或我如何实现我的建议,请建议。

    如果您不明白这个问题,请告诉我。它不是一个致命的,但它是一个恼人的错误。

    谢谢。

2 个答案:

答案 0 :(得分:0)

这是我学到的难点:

Filter实际上与AsyncTask相似。如果您有Filter,则不需要AsyncTask

  • performFiltering在非UI背景线程中运行 - 就像doInBackground一样。

  • publishResults仅在完成performFiltering后才在UI线程中运行 - 就像onPostExecute一样。

修改代码,将doInBackground的逻辑直接放入performFiltering。这将大大简化您的代码,并使其按您希望的方式工作。

答案 1 :(得分:0)

每次启动搜索时,您都声明DownloadLocations对象是新的,尝试将DownloadLocations AsyncTask声明为全局变量。

public class LocationAutoCompleteAdapter extends ArrayAdapter<LocationBean> implements Filterable {

Context context;
LayoutInflater inflater;
ArrayList<LocationBean> list, tempList, suggestions;
DownloadLocations exec = new DownloadLocations();

Filter nameFilter = new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults filterResults = new FilterResults();
        if (constraint != null) {
            try {
                // Downloads location list
                String term = constraint.toString();
                Log.e(Constants.TAG, "CHARACTER: " + term);
                if (exec.getStatus() == AsyncTask.Status.RUNNING) {
                    exec.cancel(true);
                } else {
                    exec = new DownloadLocations();
                    list = exec.execute(term).get();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            filterResults.values = list;
            filterResults.count = list.size();
        }
        return 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 locations : filterList) {
                add(locations);
            }
            notifyDataSetChanged();
        }
    }
};

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

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

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 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;
}

class ViewHolder {
    TextView name, state;
}

private class DownloadLocations extends AsyncTask<String, Void, ArrayList<LocationBean>> {

    @Override
    protected ArrayList<LocationBean> doInBackground(String... params) {
        if (!isCancelled()) {
            try {
                //Create a new COUNTRY SEARCH url Ex "search.php?term=india"
                URL url = new URL(Api.LOCATION_URL + params[0]);

                HttpsURLConnection conn = Constants.getInitHttpsURLConnectionGET(url);

                String locationResponse = Constants.getStringFromConnection(conn);

                // INIT ArrayList
                ArrayList locationList = new ArrayList<LocationBean>();
                locationList.clear();

                // PARSE RESPONSE
                JSONObject locationResponseJsonObject = new JSONObject(locationResponse);
                Log.e(Constants.TAG, "RESPONSE: " + locationResponseJsonObject);

                JSONArray result = locationResponseJsonObject.getJSONArray(Constants.KEY_LOCATION_RESULTS);

                for (int i = 0; i < result.length(); i++) {
                    JSONObject locationObject = result.getJSONObject(i);

                    String id = locationObject.getString(Constants.KEY_LOCATION_ID);
                    String state = locationObject.getString(Constants.KEY_LOCATION_STATE);
                    String name = locationObject.getString(Constants.KEY_LOCATION_NAME);
                    String district = locationObject.getString(Constants.KEY_LOCATION_TEXT);

                    locationList.add(new LocationBean(id, name, district, state));
                }
                return locationList;

            } catch (Exception e) {
                Log.d("HUS", "EXCEPTION " + e);
                return null;
            }
        } else {
            return null;
        }
    }
}

}