Android ArrayAdapter是从AutoCompleteTextAdapter中的Web服务更新的

Android ArrayAdapter是从AutoCompleteTextAdapter中的Web服务更新的,android,android-asynctask,android-arrayadapter,autocompletetextview,Android,Android Asynctask,Android Arrayadapter,Autocompletetextview,我有一个使用ArrayAdapter的AutocompleteTextView。当文本更改时,将从Web服务更新适配器。这个更新是在一个异步任务中完成的,这应该是一个好的实践。这或多或少会起作用,因为每次按下键后的建议都基于在上一次按下键时检索到的字符串。 这个页面有几个问题,但是没有一个答案适合我。无论如何,我有一个解决方案,但效率很低,我不知道为什么“官方解决方案”会失败 我认为关键在于在后台使用udpated de ArrayAdapter的功能。这就是我在对Web服务的异步调用中所做的:

我有一个使用ArrayAdapter的AutocompleteTextView。当文本更改时,将从Web服务更新适配器。这个更新是在一个异步任务中完成的,这应该是一个好的实践。这或多或少会起作用,因为每次按下键后的建议都基于在上一次按下键时检索到的字符串。 这个页面有几个问题,但是没有一个答案适合我。无论如何,我有一个解决方案,但效率很低,我不知道为什么“官方解决方案”会失败

我认为关键在于在后台使用udpated de ArrayAdapter的功能。这就是我在对Web服务的异步调用中所做的:

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());
        }
    }
}
私有类DoAutoCompleteSearch扩展了异步任务{
@凌驾
受保护的映射doInBackground(字符串…参数){
//向Web服务查询数据
Map autoComplete=GetResource.dataList(参数[0]);
返回自动完成;
}
@凌驾
受保护的void onPostExecute(映射结果){
//mAutoCompleteAdapter.clear();*这应该可以工作,但不能*
/*如果在AutoCompleteTextView中设置了一个新适配器,那么整个过程都可以正常工作*/
mAutoCompleteAdapter=newArrayAdapter(mAutoCompleteAdapter.getContext(),android.R.layout.simple\u下拉菜单\u项目\u 1line);
mACTV.setAdapter(MautCompletAdapter);
for(Map.Entry:result.entrySet()){
mAutoCompleteAdapter.add(entry.getKey());
}
}
}

我试过使用mAutoCompleteAdapter.clear()并在任何地方设置mAutoCompleteAdapter.notifyDataSetChanged(),但都没有用。

我也尝试了很多方法来让这种方法起作用,但没有比你更成功。但是我找到了另一种方法来实现你想要的;扩展阵列适配器并实现可过滤。当工作线程中的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;
    }
}
公共类MyAutoCompleteAdapter扩展ArrayAdapter实现可过滤{
private List mData=new ArrayList();
专用服务器mServer;
公共MyAutoCompleteAdapter(服务器、上下文、int-textViewResourceId){
super(上下文,textViewResourceId);
mServer=服务器;
}
@凌驾
public int getCount(){
返回mData.size();
}
@凌驾
公共字符串getItem(int索引){
返回mData.get(索引);
}
@凌驾
公共过滤器getFilter(){
过滤器myFilter=新过滤器(){
@凌驾
受保护的筛选器结果性能筛选(CharSequence约束){
//此方法在工作线程中调用
FilterResults FilterResults=新的FilterResults();
if(约束!=null){
试一试{
//下面是获取数据的方法(同步)
//从服务器
List results=mServer.searchForItems(constraint.toString());
filterResults.values=结果;
filterResults.count=结果.size();
}
捕获(例外e){}
}
返回过滤器结果;
}
@凌驾
受保护的void publishResults(CharSequence Contrint、FilterResults结果){
if(results!=null&&results.count>0){
mData=(列表)results.values;
notifyDataSetChanged();
}
否则{
notifyDataSetionValidated();
}
}
};
返回myFilter;
}
}

编辑:我改进了上述代码,因为我有时会遇到异常
java.lang.IllegalStateException:适配器的内容已更改,但ListView未收到通知
。为了解决这个问题,我将
mData
的更新移动到
publishResults()

这个代码片段在我的应用程序中对我很有用。将其放入包含
列表视图的活动中:

@Override
public void onActivityResumed() //
{
    if (favoritesHaveChanged(activity, productString)) //
    {
        m_adapter.clear();
        performAsyncTaskWithCallBack(activity);
    }
}
回调将是触发的事件侦听器。通常使用
AsyncTasks
时,您可以在
AsyncTask
中使用
onPostExecute()