2011-01-05 32 views
5

Đối với số AutoCompleteTextView Tôi cần tìm nạp dữ liệu từ dịch vụ web. Vì nó có thể mất một ít thời gian tôi không muốn thread UI không được đáp ứng, vì vậy tôi cần bằng cách nào đó để lấy dữ liệu trong một thread riêng biệt. Ví dụ, trong khi lấy dữ liệu từ SQLite DB, nó rất dễ thực hiện với phương thức CursorAdapter - runQueryOnBackgroundThread. Tôi đang tìm kiếm các bộ điều hợp khác như ArrayAdapter, BaseAdapter, nhưng không thể tìm thấy bất kỳ điều gì tương tự ...Tìm nạp AutoCompleteTextView các đề xuất từ ​​dịch vụ theo từng chủ đề riêng lẻ

Có cách nào dễ dàng để đạt được điều này không? Tôi không thể chỉ sử dụng trực tiếp ArrayAdapter vì danh sách đề xuất là động - tôi luôn tìm nạp danh sách đề xuất tùy thuộc vào đầu vào của người dùng, do đó, nó không thể được tìm nạp trước và được lưu trong bộ nhớ cache để sử dụng ...

Nếu ai đó có thể đưa ra một số mẹo hoặc các ví dụ về chủ đề này - sẽ tuyệt vời!

Trả lời

9

CHỈNH SỬA: Đã thêm cách ngây thơ để tránh menu thả xuống hiển thị khi bạn nhấp vào đề xuất.

tôi làm điều gì đó như thế này trong ứng dụng của tôi:

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

giải pháp này có một số vấn đề trong trường hợp của tôi, trình đơn thả xuống không hiển thị cho đến khi tôi nhấn phím 'xóa' trong bảng phím chức năng để xóa văn bản đã nhập, nó rất có dây. – Longerian

+0

Điều này thực sự đã giúp tôi rất nhiều! Cám ơn! – ymerdrengene

1

có cùng một giải pháp ngoại trừ vấn đề là mọi thứ đều tốt (biến được cập nhật khi tôi gỡ lỗi) nhưng autocomplete lấp đầy kì lạ như trong

khi tôi nhập sco nó có kết quả nhưng không hiển thị trong danh sách nhưng khi tôi backspace nó cho thấy kết quả cho sco. Trong gỡ lỗi tất cả các biến được cập nhật mà chỉ cho tôi biết rằng giao diện người dùng không nhận được cập nhật cho AutoCompleteTextView. như khi tôi backspace nó được kích hoạt để cập nhật và sau đó nó cho thấy danh sách máy tính trước đó sau đó nó (trong thời gian có nghĩa là nó cập nhật nó với các mục danh sách mới cho chuỗi tìm kiếm mới bất cứ ai chạy vào vấn đề này?

10

Với cách tiếp cận Tôi đoán đó là do việc lọc các kết quả được thực hiện không đồng bộ bởi lớp lọc, do đó có thể có vấn đề khi sửa đổi ArrayList của Adapter trong chuỗi ui trong khi lọc là thực hiện.

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

Tuy nhiên với cách tiếp cận sau tất cả mọi thứ làm việc tố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

Bằng cách ghi đè tất cả các phương thức cơ bản và sử dụng cấu trúc dữ liệu của riêng bạn (mSubData), bạn đã mất đi lợi ích của lớp con, bao gồm độ an toàn của chuỗi mà lớp cha đảm bảo cho dữ liệu. Chỉ cần sử dụng các phương thức add()/addAll()/clear() của lớp cha. Họ cũng sẽ tự động thông báo cho người nghe. Và bạn sẽ giữ an toàn luồng. – Risadinha

Các vấn đề liên quan