如何使用AutoCompleteTextView并使用来自Web API的数据填充它?

AJ.*_*AJ. 81 networking android filter autocompletetextview

我想AutoCompleteTextView在我的活动中使用an ,并通过查询Web API将数据填充为用户类型.我该怎么做呢?

我是否创建了一个新类并重写AutoCompleteTextView.performFiltering,或者我是否使用自定义列表适配器并提供android.widget.Filter覆盖performFiltering 的自定义?

或者有更好的方法来获得我的最终目标吗?

我做了一些类似的事情,但是它用于快速搜索框,它涉及实现服务,但我相信这不是我想要做的.

AJ.*_*AJ. 99

我想出了一个解决方案,我不知道它是否是最好的解决方案,但它看起来效果很好.我所做的是创建了一个扩展ArrayAdapter的自定义适配器.在自定义适配器中,我覆盖了getFilter并创建了我自己的Filter类,它覆盖了performFiltering.这将启动一个新线程,因此它不会中断UI.以下是一个准系统示例.

MyActivity.java

public class MyActivity extends Activity {
    private AutoCompleteTextView style;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        style = (AutoCompleteTextView) findViewById(R.id.style);
        adapter = new AutoCompleteAdapter(this, android.R.layout.simple_dropdown_item_1line); 
        style.setAdapter(adapter);
    }
}
Run Code Online (Sandbox Code Playgroud)

AutoCompleteAdapter.java

public class AutoCompleteAdapter extends ArrayAdapter<Style> implements Filterable {
    private ArrayList<Style> mData;

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

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public Style 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) {
                    // A class that queries a web API, parses the data and returns an ArrayList<Style>
                    StyleFetcher fetcher = new StyleFetcher();
                    try {
                        mData = fetcher.retrieveResults(constraint.toString());
                    }
                    catch(Exception e) {
                        Log.e("myException", e.getMessage());
                    }
                    // Now assign the values and count to the FilterResults object
                    filterResults.values = mData;
                    filterResults.count = mData.size();
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence contraint, FilterResults results) {
                if(results != null && results.count > 0) {
                notifyDataSetChanged();
                }
                else {
                    notifyDataSetInvalidated();
                }
            }
        };
        return myFilter;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @bugfixr在您的类上添加一个公共toString方法.在我的例子中它是:public String toString(){return name; } (6认同)
  • 好的解决方案 - 正是我需要的.如果我可能会问......你会将样式返回到simple_dropdown_item_1line布局.如何从Style类中检索适当的值?对我来说,这是我创建的一个类,我希望文本值getStyleName显示在我的列表项中,但它只显示类的名称. (3认同)
  • @AJ。谢谢你的回答。由于答案已有 6 年历史,我想知道它是否仍然是最佳实践,或者是否有新的更好的方法来实现自动完成元素。 (2认同)
  • @Tohid这仍然是最好的答案,只能添加一件事。那是一个延迟的处理程序可以用来触发API调用。如此处所示:https://www.truiton.com/2018/06/android-autocompletetextview-suggestions-from-webservice-call/ (2认同)

raz*_*zak 7

扩展AJ.上面的答案,以下自定义适配器包括服务器请求和json解析的处理:

class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable
{
    private ArrayList<String> data;
    private final String server = "http://myserver/script.php?query=";

    AutoCompleteAdapter (@NonNull Context context, @LayoutRes int resource)
    {
        super (context, resource);
        this.data = new ArrayList<>();
    }

    @Override
    public int getCount()
    {
        return data.size();
    }

    @Nullable
    @Override
    public String getItem (int position)
    {
        return data.get (position);
    }

    @NonNull
    @Override
    public Filter getFilter()
    {
        return new Filter()
        {
            @Override
            protected FilterResults performFiltering (CharSequence constraint)
            {
                FilterResults results = new FilterResults();
                if (constraint != null)
                {
                    HttpURLConnection conn = null;
                    InputStream input = null;
                    try
                    {
                        URL url = new URL (server + constraint.toString());
                        conn = (HttpURLConnection) url.openConnection();
                        input = conn.getInputStream();
                        InputStreamReader reader = new InputStreamReader (input, "UTF-8");
                        BufferedReader buffer = new BufferedReader (reader, 8192);
                        StringBuilder builder = new StringBuilder();
                        String line;
                        while ((line = buffer.readLine()) != null)
                        {
                            builder.append (line);
                        }
                        JSONArray terms = new JSONArray (builder.toString());
                        ArrayList<String> suggestions = new ArrayList<>();
                        for (int ind = 0; ind < terms.length(); ind++)
                        {
                            String term = terms.getString (ind);
                            suggestions.add (term);
                        }
                        results.values = suggestions;
                        results.count = suggestions.size();
                        data = suggestions;
                    }
                    catch (Exception ex)
                    {
                        ex.printStackTrace();
                    }
                    finally
                    {
                        if (input != null)
                        {
                            try
                            {
                                input.close();
                            }
                            catch (Exception ex)
                            {
                                ex.printStackTrace();
                            }
                        }
                        if (conn != null) conn.disconnect();
                    }
                }
                return results;
            }

            @Override
            protected void publishResults (CharSequence constraint, FilterResults results)
            {
                if (results != null && results.count > 0)
                {
                    notifyDataSetChanged();
                }
                else notifyDataSetInvalidated();
            }
        };
    }
Run Code Online (Sandbox Code Playgroud)

并以相同的方式使用它:

public class MyActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        AutoCompleteTextView textView = (AutoCompleteTextView) findViewById (R.id.style);
        int layout = android.R.layout.simple_list_item_1;
        AutoCompleteAdapter adapter = new AutoCompleteAdapter (this, layout); 
        textView.setAdapter (adapter);
    }
}
Run Code Online (Sandbox Code Playgroud)