2011-11-11 105 views
27

我想通過從REST風格的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服務註冊爲內容提供者。 (它的形式http://www.blah.com/query?term=XX,其中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個字符後開始暗示;然而,如果我的游泳池很大,那麼我應該等到兩個字符才能提出任何建議 - 出於提高效率的目的。你一定要保持1或2。 – serkanozel

18

有在使用谷歌地圖API的遠程數據來填充AutoCompleteTextView here這個話題相當不錯的教程。

如果您需要緩存版本,我從here檢索它。 原始教程已被刪除,但基本上你需要用類似於下面所示的方法編寫一個帶有自定義過濾器的ArrayAdapter,並將其分配給AutoCompleteTextView。

注意:您需要實現一個方法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 trhead – 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

既然我不能添加評論,我給一個新的答案 沒有必要清除適配器或致電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. 
相關問題