Android 如何在保留字符状态的情况下向autocompletetextview动态添加建议

Android 如何在保留字符状态的情况下向autocompletetextview动态添加建议,android,autocompletetextview,notifydatasetchanged,android-filterable,Android,Autocompletetextview,Notifydatasetchanged,Android Filterable,问题描述: 我在AutoCompleteTextView中遇到了一些问题,每次按键后都必须显示建议。 问题是,建议列表是动态的,就像谷歌的建议功能一样。 这意味着新的建议应该在用户不断输入时添加,并且所有匹配的旧建议都应该显示出来 例如 我写“te”,然后它应该显示以前的建议,比如“test1”和“test2”,以及我将从webapi获得的新建议。假设WebAPI给了我“tea”和“tension”两个词 现在,AutoCompleteTextView将“te”作为字符串,下面显示所有四个建议

问题描述:

我在AutoCompleteTextView中遇到了一些问题,每次按键后都必须显示建议。 问题是,建议列表是动态的,就像谷歌的建议功能一样。 这意味着新的建议应该在用户不断输入时添加,并且所有匹配的旧建议都应该显示出来

例如

我写“te”,然后它应该显示以前的建议,比如“test1”和“test2”,以及我将从webapi获得的新建议。假设WebAPI给了我“tea”和“tension”两个词

现在,AutoCompleteTextView将“te”作为字符串,下面显示所有四个建议

这正是我要找的

看起来很简单,但它表现出一种奇怪的行为

我正在使用默认的ArrayAdapter类实例,我正在全局声明该实例

arrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,suggestions);
word.setAdapter(arrayAdapter);
刷新与此相关的数据观察者和视图(在本例中为AutoCompleteListView)

但它结束了这些建议

当我不使用
notifyDataSetChanged()时它显示所有建议,无论我输入了什么字符

我尝试了许多建议的自定义过滤器,但没有一个有用,因为我无法使用notifyDataSetChanged()

为了避免混淆,我发布了一张图片


我不明白为什么
notifyDataSetChanged()它不工作。我没有对同一arrayAdapter实例使用任何其他列表引用。我真的怀疑这是否是一个引用问题。

最简单的方法之一(将代码放在onCreate中):

编辑:添加wikipedia免费opensearch(如果不起作用,请尝试)

AutoCompleteTextView actv=新的AutoCompleteTextView(此);
动作设定阈值(1);
字符串[]from={“name”,“description”};
int[]to={android.R.id.text1,android.R.id.text2};
SimpleCrsorAdapter a=新的SimpleCrsorAdapter(这个,android.R.layout.simple_列表_项_2,null,from,to,0);
a、 设置管柱转换柱(1);
FilterQueryProvider=新的FilterQueryProvider(){
@凌驾
公共游标运行查询(CharSequence约束){
//在后台线程中运行
Log.d(标记“runQuery约束:”+constraint);
if(约束==null){
返回null;
}
String[]columnNames={BaseColumns.\u ID,“name”,“description”};
MatrixCursor c=新MatrixCursor(列名称);
试一试{
字符串URL字符串=”https://en.wikipedia.org/w/api.php?" +
“action=opensearch&search=“+约束+
“&limit=8&namespace=0&format=json”;
URL=新URL(URL字符串);
InputStream=url.openStream();
BufferedReader reader=新的BufferedReader(新的InputStreamReader(流));
字符串jsonStr=reader.readLine();
//输出[“查询”、[“n0”、“n1”、…]、“d0”、“d1”、…]
JSONArray json=新的JSONArray(jsonStr);
JSONArray name=json.getJSONArray(1);
JSONArray descriptions=json.getJSONArray(2);
对于(int i=0;i
您已经在ArrayAdapter的子类中实现了custome筛选器,在执行筛选器方法中,您必须执行网络调用并从服务器获取数据。您可以在主arraylist中设置此数据。

何时以及如何将web结果添加到适配器?@pskink:我将其添加到arraylist的建议中。然后调用notifyDataSetChanged()。我在postExecute()中执行此操作从WebApi获取结果的Asynctask。您应该在适配器的筛选器的PerformFilter/publishResults方法中执行此操作。我还没有尝试过。让我检查一下。或者您可以使用现有筛选器,如CursorFilter及其与CursorAdapter的集成,请参见下面的答案。我找到了解决方案,你的评论是对的,它帮助我部分解决了这个问题。虽然我也有一些其他问题,我目前正在工作。我并没有通过这种方式来获得答案,因为我不想将数据库用于这个单一目的。我非常感谢你的全力支持,并为此感谢你。谢谢你的帮助。我不使用任何数据库,数据是从json web服务读取的。到目前为止,我尝试了很多不同的东西:TextWatcher、AsyncTask等等。这正是我想要的!我能找到的最好的代码。很好用@奥利维耶普。简单但有效,不是吗?不幸的是,这里90%的人仍然希望与那些观察者、定制阵列适配器、异步任务等进行斗争,即使他们看到了这么简单的解决方案,我也不知道为什么…@pskink我是其中之一^^我不知道这样做可以做到。很高兴我找到了你的代码。此外,当你通过互联网、StackOverflow等进行搜索时,你的答案肯定不是突出显示的答案!
arrayAdapter.notifyDataSetChanged();
    AutoCompleteTextView actv = new AutoCompleteTextView(this);
    actv.setThreshold(1);
    String[] from = { "name", "description" };
    int[] to = { android.R.id.text1, android.R.id.text2 };
    SimpleCursorAdapter a = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, from, to, 0);
    a.setStringConversionColumn(1);
    FilterQueryProvider provider = new FilterQueryProvider() {
        @Override
        public Cursor runQuery(CharSequence constraint) {
            // run in the background thread
            Log.d(TAG, "runQuery constraint: " + constraint);
            if (constraint == null) {
                return null;
            }
            String[] columnNames = { BaseColumns._ID, "name", "description" };
            MatrixCursor c = new MatrixCursor(columnNames);
            try {
                String urlString = "https://en.wikipedia.org/w/api.php?" +
                        "action=opensearch&search=" + constraint +
                        "&limit=8&namespace=0&format=json";
                URL url = new URL(urlString);
                InputStream stream = url.openStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                String jsonStr = reader.readLine();
                // output ["query", ["n0", "n1", ..], ["d0", "d1", ..]]
                JSONArray json = new JSONArray(jsonStr);
                JSONArray names = json.getJSONArray(1);
                JSONArray descriptions = json.getJSONArray(2);
                for (int i = 0; i < names.length(); i++) {
                    c.newRow().add(i).add(names.getString(i)).add(descriptions.getString(i));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return c;
        }
    };
    a.setFilterQueryProvider(provider);
    actv.setAdapter(a);
    setContentView(actv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));