2011-01-05 27 views
5

hizmetine ilişkin önerileri getirme AutoCompleteTextView için Bir web servisinden veri almam gerekiyor. UI iş parçacığının yanıt vermemesi için biraz zaman alabildiğinden, verileri bir şekilde ayrı bir iş parçacığına almam gerekiyor. Örneğin, SQLite DB'den veri alırken, CursorAdapter yöntemiyle çok kolay yapılır - runQueryOnBackgroundThread. ArrayAdapter, BaseAdapter gibi diğer bağdaştırıcılara bakıyordum, ancak benzer bir şey bulamadım.Ayrı iş parçacığı içinde

Bunu nasıl başarmanın kolay bir yolu var mı? Öneriler listesi dinamik olduğu için doğrudan ArrayAdapter'u kullanamıyorum - Kullanıcı girişine bağlı olarak her zaman öneri listesini getiriyorum, bu nedenle daha fazla kullanım için önceden getirilemez ve önbelleğe alınamaz ...

Birisi bazı ipuçları verebilirse veya bu konuyla ilgili örnekler - harika olurdu!

cevap

9

DÜZENLEME: Bir öneriyi tıklattığınızda gösterilen açılır pencereden kaçınmak için naif bir yol eklendi.

benim app böyle bir şey yapmak:

private AutoCompleteTextView mSearchbar; 
private ArrayAdapter<String> mAutoCompleteAdapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    mAutoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line); 
    mSearchbar = (AutoCompleteTextView) findViewById(R.id.searchbar); 
    mSearchbar.setThreshold(3); 
    mSearchbar.setAdapter(mAutoCompleteAdapter); 
    mSearchbar.addTextChangedListener(new TextWatcher() { 

     private boolean shouldAutoComplete = true; 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      shouldAutoComplete = true; 
      for (int position = 0; position < mAutoCompleteAdapter.getCount(); position++) { 
       if (mAutoCompleteAdapter.getItem(position).equalsIgnoreCase(s.toString())) { 
        shouldAutoComplete = false; 
        break; 
       } 
      } 

     } 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      if (shouldAutoComplete) { 
       new DoAutoCompleteSearch().execute(s.toString()); 
      } 
     } 
    } 
} 

private class DoAutoCompleteSearch extends AsyncTask<String, Void, ArrayList<String>> { 
    @Override 
    protected ArrayList<String> doInBackground(String... params) { 
     ArrayList<String> autoComplete = new ArrayList<String>(); 
     //do autocomplete search and stuff. 
     return autoComplete; 
    } 

    @Override 
    protected void onPostExecute(ArrayList<String> result) { 
     mAutoCompleteAdapter.clear(); 
     for (String s : result) 
      mAutoCompleteAdapter.add(s); 
    } 
} 
+0

Bu çözümde benim sorunumda bir sorun var, açılan menüyü silmek için softkey panosundaki 'delete' tuşuna basana kadar açılan menü görünmüyor, o kadar kablolu. – Longerian

+0

Bu gerçekten bana çok yardımcı oldu! Teşekkürler! – ymerdrengene

1

sorun, (i hata ayıklarken değişkenler güncellenir) her şey iyi olduğunu ancak otomatik tamamlama

gibi esrarlı doldurur dışında aynı çözüm vardı

Sco yazarken sonuçları var ama listede göstermiyor ama geri döndüğümde, sonuç sco için gösteriliyor. Hata ayıklamada, yalnızca UI'nin AutoCompleteTextView için güncelleştirilmediğini bildiren tüm değişkenler güncelleştirilir. ben backspace güncelleme için tetiklenir ve daha sonra bilgisayar listesi daha sonra gösterir o zaman (bu arada yeni arama dizesi için yeni liste öğeleri ile günceller. kimse bu sorunla karşılaştı?

10

Yaklaşım ile yukarıda, ben çok hızlı yazarken bu sorunları vardı.Aslında sanırım filtreleme, sonuçların filtrelenmesi filtre sınıfı tarafından eşzamansız yapıldığı için filtreleme sırasında ui iş parçacığı içinde Bağdaştırıcı ArrayList değiştirirken sorun olabilir yaklaşım her şeyi aşağıdaki Ancak bitti.

http://developer.android.com/reference/android/widget/Filter.html

iyi çalıştı.

public class MyActivity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     MyAdapter myAdapter = new MyAdapter(this, android.R.layout.simple_dropdown_item_1line); 

     AutoCompleteTextView acTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1); 
     acTextView.setAdapter(myAdapter); 
    } 
} 

public class MyAdapter extends ArrayAdapter<MyObject> { 
    private Filter mFilter; 

    private List<MyObject> mSubData = new ArrayList<MyObject>(); 
    static int counter=0; 

    public MyAdapter(Context context, int textViewResourceId) { 
     super(context, textViewResourceId); 
     setNotifyOnChange(false); 

     mFilter = new Filter() { 
     private int c = ++counter; 
     private List<MyObject> mData = new ArrayList<MyObject>(); 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      // This method is called in a worker thread 
      mData.clear(); 

      FilterResults filterResults = new FilterResults(); 
      if(constraint != null) { 
      try { 
       // Here is the method (synchronous) that fetches the data 
       // from the server  
       URL url = new URL("..."); 
       URLConnection conn = url.openConnection(); 
       BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
       String line = ""; 

       while ((line = rd.readLine()) != null) { 
         mData.add(new MyObject(line)); 
       } 
      } 
      catch(Exception e) { 
      } 

      filterResults.values = mData; 
      filterResults.count = mData.size(); 
      } 
      return filterResults; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence contraint, FilterResults results) { 
      if(c == counter) { 
      mSubData.clear(); 
       if(results != null && results.count > 0) { 
       ArrayList<MyObject> objects = (ArrayList<MyObject>)results.values; 
       for (MyObject v : objects) 
        mSubData.add(v); 

       notifyDataSetChanged(); 
       } 
       else { 
       notifyDataSetInvalidated(); 
       } 
      } 
     } 
    }; 
    } 

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

    @Override 
    public MyObject getItem(int index) { 
    return mSubData.get(index); 
    } 

    @Override 
    public Filter getFilter() { 
    return mFilter; 
    } 
} 
+0

Tüm temel yöntemleri geçersiz kılarak ve kendi veri yapınızı (mSubData) kullanarak, süper sınıfın verileri garanti ettiği iplik güvenliği dahil olmak üzere, alt sınıflamanın yararını kaybettiniz. Sadece süper sınıfın add()/addAll()/clear() yöntemlerini kullanın. Onlar da dinleyicileri otomatik olarak bilgilendirecekler. Ve iplik güvenliğini koruyacaksınız. – Risadinha

İlgili konular