我在Android中创建了一个动态AutoCompleteTextView。它有以下组件。
方案: 现在当我开始输入AutoCompleteTextView时,在输入第一个字符后,它会启动异步调用。然后,当我开始输入更多字符时,它会再次为每个字符调用异步,并通过过滤器发布结果。
问题: 问题是,当为第一个字符调用第一个AsyncTask时,结果列表将在AutoCompleteTextView的下拉列表中发布,而我仍在键入TextView。然后我必须等待发布最新列表,这需要花费很多时间,因为每个字符都是异步执行。
代码: 下面是我正在使用的适配器。
typedef int l;
mydecltype(l) x; // int x;
mydecltype(x) y; // int y;
我的想法:我认为在发布结果之前杀死正在运行的AsyncTask将是一个很好的解决方案。但我无法这样做。如果您有更好的解决方案或我如何实现我的建议,请建议。
如果您不明白这个问题,请告诉我。它不是一个致命的,但它是一个恼人的错误。
谢谢。
答案 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;
}
}
}
}