2011-11-11 23 views
27

RESTfulなWebサービスからリストを取得することで、AutoCompleteTextviewの提案を定期的に変更し、スムーズに動作させることはできません。私は働いていることを確認するための提案のハードコーディングされたリストを設定します。AutoCompleteTextViewアダプタを動的に更新する

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, new String[] {"Hi", "Ho"}); 
speciesName.setAdapter(adapter);//my autocomplete tv 

は私がのTextViewにTextWatcherを持っていると、ノンブロッキングコールを起動し、テキストの変更が提案の新しいリストを取得するとき - 新しいリストを取得するこの部分は正常に動作しています。それから私はそうのように、アダプタをリセットしたい:

public void setOptionsAndUpdate(String[] options) { 
    Log.d(TAG, "setting options"); 
    //speciesName.setAdapter((ArrayAdapter<String>)null); 
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, options); 
    speciesName.setAdapter(adapter); 
} 

このメソッドが呼び出されますが、動作しません - 提案のリストが消えいずれか、または表示された提案はsetAdapterへの呼び出しにもかかわらず、変更されません。

これは適切なアプローチですか?私はSimpleCursorAdapterを見ましたが、私のWebサービスをコンテンツプロバイダとして登録する方法が見当たりませんでした。 (これは、XXは自分のアプリケーションから入力されたフォームhttp://www.blah.com/query?term=XX、のだ、と応答は、文字列のJSON配列である。)

+0

私は似たようなことをしています! http://stackoverflow.com/questions/12854336/autocompletetextview-backed-by-cursorloader – toobsco42

答えて

14

これは私が私のAutoCompleteTextView更新する方法です。もちろん今

String[] data = terms.toArray(new String[terms.size()]); // terms is a List<String> 
ArrayAdapter<?> adapter = new ArrayAdapter<Object>(activity, android.R.layout.simple_dropdown_item_1line, data); 
keywordField.setAdapter(adapter); // keywordField is a AutoCompleteTextView 
if(terms.size() < 40) keywordField.setThreshold(1); 
else keywordField.setThreshold(2); 

を、これは静的であり、空中の提案に対処しませんが、私はまた、あなたがAutoCompleteTextViewに割り当てた後、変更のためのアダプターを通知することをお勧めすることができます

adapter.notifyDataSetChanged(); 

・ホープ、このことができます。

-serkan

+0

ありがとう、それは私のためにそれを解決します。 – jaybee

+0

@serkan:これは私にとって必要なものです。しかし、私はしきい値が更新されていないと思いますよね?したがって、あなたの例では、 'terms.size()<40'が最初にあれば、閾値は永遠に1にとどまります。もちろん、そのコード行を再度実行して更新することができます。ありがとう! –

+0

ルイスに感謝します。さて、私がやっていることはちょっとしたことがあれば、1人のキャラクターが登場した後でも提案を始めることができます。しかし、私のプールが大きければ、私は2つの文字が何かを提案するまで待つべきです - 効率化のためです。あなたは確かにそれを常に1または2にしておきます。 – serkanozel

18

AutoCompleteTextView hereを取り込むためにGoogleマップAPIでリモートデータを使用して、このトピックに関するかなり良いチュートリアルがありました。

キャッシュされたバージョンが必要な場合は、hereから取得しました。 元のチュートリアルは削除されましたが、基本的に、以下に示すのと同様の方法でカスタムフィルタを使用してArrayAdapterを作成し、それをAutoCompleteTextViewに割り当てる必要があります。

注:autocompleteアイテムを同期的にフェッチして返すために必要な操作を行うautocomplete()メソッドを実装する必要があります。フィルタはバックグラウンドスレッドで呼び出されるため、メインUIスレッドはブロックされません。

private class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable { 
private ArrayList<String> resultList; 

public PlacesAutoCompleteAdapter(Context context, int textViewResourceId) { 
    super(context, textViewResourceId); 
} 

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

@Override 
public String getItem(int index) { 
    return resultList.get(index); 
} 

@Override 
public Filter getFilter() { 
    Filter filter = new Filter() { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      FilterResults filterResults = new FilterResults(); 
      if (constraint != null) { 
       // Retrieve the autocomplete results. 
       resultList = autocomplete(constraint.toString()); 

       // Assign the data to the FilterResults 
       filterResults.values = resultList; 
       filterResults.count = resultList.size(); 
      } 
      return filterResults; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      if (results != null && results.count > 0) { 
       notifyDataSetChanged(); 
      } 
      else { 
       notifyDataSetInvalidated(); 
      } 
     }}; 
    return filter; 
} 
} 
+0

パーフェクト!そのリンクはただの甘いものです!ありがとう! :) – Jona

+0

ネットワーク通話をするときにUIの頭をブロックしないでください – jonney

+0

私はUIスレッドについて同じ質問がありました。 @ manyobjectはあなたを証明することができますか? –

28

アダプターのデータを動的に追加したり変更したりするときに、adapter.notifyDataSetChanged()を使用したことはありませんでした。私の状況では、私は非同期的に外部APIを打ち、定期的に補完データのリストを取得していました。

このコードでは、アダプタをクリアして、期待どおりに新しいデータを追加します。しかし、データを強制的に表示するには、getFilter()。Filterメソッドを呼び出す必要がありました。また、私は、明示的にAutocompleteTextView内の現在のテキストに基づいてフィルターをかけなければなりませんでした。これは、私のAPIコールが非同期であったためです。私はコメントを追加することはできませんので

adapter.clear(); 
for (Map<String, String> map : completions) { 
    adapter.add(map.get("name")); 
} 

//Force the adapter to filter itself, necessary to show new data. 
//Filter based on the current text because api call is asynchronous. 
adapter.getFilter().filter(autocompleteTextView.getText(), null); 
+0

の代わりに 'null'を渡すと、' AutoCompleteTextView'を渡して、 'AutoCompleteTextView.performFiltering()'と同じように動作させることができます - 通常、テキストが変更された後に呼び出されるメソッド – kassim

+0

この。私はあなたにビールを持っています:) – codingpuss

+0

ありがとう@GLee。あなたは私の一日を作った。 –

2

、i)は、アダプタをクリアするか、adapter.getFilterを(呼び出す必要はありません新しい回答 を与えている。(...)フィルタ... AutoCompleteTextViewアダプターを動的に更新するには、新しい項目をアダプターに追加し、setAdapterをもう一度追加します。元の質問の例では、私は次のように試してみましたが、動作します(以下のコードはアダプタの初期設定を示していません。アダプターの更新は、ArrayAdapterに関連付けられたListを更新するコードの横に置くことができます。

adapter.add(String newSuggestion); // this goes inside a loop for adding multiple suggestions 
    speciesName.setAdapter(adapter) ; // speciesName is an AutoCompleteTextView as given in the original question. 
関連する問題