我在Android中创建了一个动态的AutoCompleteTextView。它有以下组件。杀死AsyncTask在perfromFilter中调用动态AutoCompleteTextView
- ArrayAdapter与我自定义的POJO。
- 适配器实现可过滤。
- 此过滤器调用AsyncTask,该AsyncTask根据获取的字符或约束获取所有数据。
- 获取所有数据后,AsyncTask解析数据,然后将列表返回给过滤器进行发布。
方案: 现在,当我开始输入在AutoCompleteTextView,进入第一个字符后,它会启动异步调用。然后,当我开始输入更多字符时,它会再次为每个字符调用异步,并通过过滤器发布结果。
问题: 的问题是,当第一的AsyncTask被称为第一个字符,结果列表发表在降AutoCompleteTextView下来,而我还在原地在TextView中键入。然后,我必须等待最新的列表发布,这需要很长时间,因为每个字符都是异步执行的。
代码: 下面是我正在使用的适配器。
public class LocationAutoCompleteAdapter extends ArrayAdapter<LocationBean> implements Filterable {
Context context;
LayoutInflater inflater;
ArrayList<LocationBean> list, tempList, suggestions;
Filter nameFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
try {
// Downloads location list
DownloadLocations exec = new DownloadLocations();
String term = constraint.toString();
Log.e(Constants.TAG, "CHARACTER: " + term);
if (exec.getStatus() == AsyncTask.Status.RUNNING) {
exec.cancel(true);
} else {
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;
}
}
}
}
我的想法:我认为,杀死正在运行的AsyncTask它发布之前,其结果将是一个很好的解决方案。但我无法这样做。建议你是否有更好的解决方案,或者如何实现我的目标。
如果您不了解问题,请让我知道。它不是致命的,但它是一个烦人的bug。
谢谢。
你知道总的位置没有? –
@SohailZahid:它总是变化的,所以如果我开始打印孟买,首先它会获取所有以M开头的地方,然后是MU,然后是MUM等等。总人数超过了lacs,因此我使用了这种方法 –