ArrayAdapter在AutoCompleteTextAdapter中从Webservice延迟更新

时间:2011-07-01 09:51:44

标签: android android-asynctask android-arrayadapter autocompletetextview

我有一个使用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(),但它没用。

2 个答案:

答案 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