【问题标题】:ArrayAdapter need to be clear even i am creating a new oneArrayAdapter 需要清楚,即使我正在创建一个新的
【发布时间】:2014-06-07 11:51:19
【问题描述】:

您好,我在理解 ArrayAdapter 的工作原理时遇到问题。我的代码正在运行,但我不知道如何。(http://amy-mac.com/images/2013/code_meme.jpg)

我有我的活动,里面有 2 个私人课程。:

public class MainActivity extends Activity {
    ...
    private void SomePrivateMethod(){
        autoCompleteTextView.setAdapter(new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_dropdown_item, new ArrayList<String>(Arrays.asList(""))));
        autoCompleteTextView.addTextChangedListener(new MyTextWatcher());
    }
    ...

    private class MyTextWatcher implements TextWatcher {
        ...
    }
    private class SearchAddressTask extends AsyncTask<String, Void, String[]> {
        ...
    }
}

现在在我的 textwatcher 类中,我调用了搜索地址任务:

@Override
public void afterTextChanged(Editable s) {
    new SearchAddressTask().execute(s.toString());
}

到目前为止一切顺利。

在我的 SearchAddressTask 中,我在 doInBackground() 上执行了一些返回正确数组的操作。

在 onPostExecute() 方法上,我尝试仅修改 AutoCompleteTextView 适配器以添加从 doInBackground() 中获得的数组中的值,但无法修改适配器:

不工作的代码:

protected void onPostExecute(String[] addressArray) {
    ArrayAdapter<String> adapter = (ArrayAdapter<String>) autoCompleteDestination.getAdapter();
    adapter.clear();
    adapter.addAll(new ArrayList<String>(Arrays.asList(addressArray)));
    adapter.notifyDataSetChanged();
    Log.d("SearchAddressTask", "adapter isEmpty : " + adapter.isEmpty()); // Returns true!!??!
}

我不明白为什么这不起作用。即使我在 UI Thread 上运行它...

我一直在调查,如果我重新创建 arrayAdapter,在 UI 中工作(显示建议),但我仍然需要清除旧适配器:

工作代码:

protected void onPostExecute(String[] addressArray) {
    ArrayAdapter<String> adapter = (ArrayAdapter<String>) autoCompleteDestination.getAdapter();
    adapter.clear();
    autoCompleteDestination.setAdapter(new ArrayAdapter<String>(NewDestinationActivity.this,android.R.layout.simple_spinner_dropdown_item, new ArrayList<String>(Arrays.asList(addressArray))));
    //adapter.notifyDataSetChanged(); // no needed
    Log.d("SearchAddressTask", "adapter isEmpty : " + adapter.isEmpty()); // keeps returning true!!??!
}

所以我的问题是,这个 ArrayAdapter 到底发生了什么?为什么我不能在我的 onPostExecute() 中修改它?如果我要重新创建适配器,为什么在 UI 中工作?那为什么我需要清除旧适配器?

我不知道这里有这么多问题需要帮助!

谢谢!!

【问题讨论】:

  • 您需要更改onPostExecute 中的列表内容并调用adapter.notifyDatasetChanged();,而不是清除适配器
  • SearchAddressTask 是做什么用的?
  • 不要个人认为,但您当前的解决方案是错误的:您根本不使用系统中已经构建的所有功能:Filter 类,当您使用它时,您将不必使用任何 Watcher ,AsyncTask,清除和设置Adapter等,阅读Filter和Filterable
  • 这对过滤器来说是一个完美的工作!
  • 是的,你解释得对,在这里查看我的答案stackoverflow.com/questions/19858843/…我如何查询维基百科网络搜索 api,它在后台使用过滤器,所以你不要自己实现过滤器

标签: android android-asynctask android-arrayadapter ui-thread textwatcher


【解决方案1】:

我听从了pskink的推荐,非常感谢!!

我将所有的职责都切换到了 ArrayAdapter 并实现了我自己的过滤器。

import java.util.ArrayList;

import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;

import com.roisoftstudio.travelalarm.gui.utils.StreetListHelper;

public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
    private ArrayList<String> mData;
    private Context context;

    public AutoCompleteAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
        this.context = context;
        mData = new ArrayList<String>();
    }

    @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) {
                FilterResults filterResults = new FilterResults();
                if (constraint != null) {
                    mData = StreetListHelper.getStreetList(context, constraint.toString());
                    filterResults.values = mData;
                    filterResults.count = mData.size();
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
            }

        };
        return myFilter;
    }
}

【讨论】:

  • 你根本不需要SearchAddressTask(performFiltering在后台线程中执行),请看我再次发布的链接
  • 您也不在 publishResults 中使用结果,而且您​​必须这样做,顺便说一句,为什么不直接使用 FilterQueryProvider?它应该很简单:您无需执行任何操作,只需返回数据即可
  • 谢谢,我删除了异步任务。不知道 performFiltering 是在另一个线程中执行的。关于FilterQueryProvider,我不知道,但它会强迫我使用游标吗?如果是这样,我想我会保持原样,我更喜欢用 string[] 执行这个简单的任务。
  • MatrixCursor 有什么问题?请注意我的整个代码,包括创建 ACTV、创建适配器、设置内容视图、查询 web api 等(添加到 onCreate 的完整工作代码)只需要 40 行代码(只有你的适配器需要更多行)
  • 好吧,我看到它是面向数据库的,我看到它包含的代码更少,但是我看到使用 Filterable 接口的代码更清晰。非常感谢您的帮助和 cmets 改进我的代码!
猜你喜欢
  • 1970-01-01
  • 2017-05-17
  • 2020-11-27
  • 1970-01-01
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
相关资源
最近更新 更多