1. ホーム
  2. android

[解決済み] AutoCompleteTextView を使用して、Web API からのデータを入力するにはどうすればよいですか?

2023-05-28 22:44:30

質問

私は AutoCompleteTextView を使用し、Web APIを照会することによってユーザーが入力するときにデータを入力したいと思います。 これを行うにはどうすればよいですか?

私は新しいクラスを作成し、オーバーライド AutoCompleteTextView.performFiltering あるいは、カスタムのリストアダプタを使用し、カスタムの android.widget.Filter を用意して、performFiltering をオーバーライドするのでしょうか?

または、私の最終目標を得るためのより良い方法がありますか?

私は似たようなことをしたことがありますが、それはクイック検索ボックスのためのもので、サービスを実装することを含んでいました。

どのように解決するのですか?

私は解決策を思いつきました。それが最善の解決策であるかどうかは分かりませんが、非常にうまく機能しているように見えます。 私が行ったのは、ArrayAdapter を継承したカスタム アダプターを作成することです。 このカスタムアダプタでは、getFilter をオーバーライドし、 performFiltering をオーバーライドする独自の Filter クラスを作成しました。 これは新しいスレッドを起動するので、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);
    }
}

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;
    }
}