我有一个使用ArrayAdapter的AutocompleteTextView。当文本更改时,适配器将从Web服务更新。这个更新是在AsyncTask中完成的,这应该是一个很好的做法。这或多或少都有效,因为按下每个键后的建议都是基于在前一个键中检索到的字符串。 这个页面有几个相关的问题,但没有一个答案适合我。无论如何,我有一个解决方案,但效率低下,我不知道为什么“官方解决方案”失败。
我认为关键在于udpates de ArrayAdapter在后台的功能。这就是我在对webservices的异步调用中所做的事情:
private class DoAutoCompleteSearch extends AsyncTask<String, Void, Map<String, String>> {
@Override
protected Map<String, String> doInBackground(String... params) {
// Ask the webservice for data
Map<String, String> autoComplete = GetResource.dataList(params[0]);
return autoComplete;
}
@Override
protected void onPostExecute(Map<String, String> result) {
//mAutoCompleteAdapter.clear(); * This should work but does not *
/* If it is set a new adapter in the AutoCompleteTextView, the whole thing works properly */
mAutoCompleteAdapter = new ArrayAdapter<String>(mAutoCompleteAdapter.getContext(), android.R.layout.simple_dropdown_item_1line);
mACTV.setAdapter(mAutoCompleteAdapter);
for (Map.Entry<String, String> entry : result.entrySet()) {
mAutoCompleteAdapter.add(entry.getKey());
}
}
}
我尝试过使用mAutoCompleteAdapter.clear()并在任何地方设置mAutoCompleteAdapter.notifyDataSetChanged(),但它没用。
答案 0 :(得分:2)
我也尝试过这种方法,但是没有比你自己更好的方法。但我找到了另一种方法来实现你想要的东西;扩展ArrayAdapter并实现Filterable。当由工作线程中的AutoCompleteTextView调用时,此类将从数据库中进行实际读取:
public class MyAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private List<String> mData = new ArrayList<String>();
private Server mServer;
public MyAutoCompleteAdapter(Server server, Context context, int textViewResourceId) {
super(context, textViewResourceId);
mServer = server;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int index) {
return mData.get(index);
}
@Override
public Filter getFilter() {
Filter myFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// This method is called in a worker thread
FilterResults filterResults = new FilterResults();
if(constraint != null) {
try {
// Here is the method (synchronous) that fetches the data
// from the server
List<String> results = mServer.searchForItems(constraint.toString());
filterResults.values = results;
filterResults.count = results.size();
}
catch(Exception e) {}
}
return filterResults;
}
@Override
protected void publishResults(CharSequence contraint, FilterResults results) {
if(results != null && results.count > 0) {
mData = (List<String>)results.values;
notifyDataSetChanged();
}
else {
notifyDataSetInvalidated();
}
}
};
return myFilter;
}
}
编辑:我改进了上述代码,因为我有时会遇到异常java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification
。为解决此问题,我将mData
的更新移至publishResults()
。
答案 1 :(得分:0)
此代码段在我的应用中为我工作。将其添加到包含ListView
:
@Override
public void onActivityResumed() //
{
if (favoritesHaveChanged(activity, productString)) //
{
m_adapter.clear();
performAsyncTaskWithCallBack(activity);
}
}
回调将是一个被触发的事件监听器。通常使用AsyncTasks
,您可以在onPostExecute()
中使用AsyncTask
。