2010-03-01 31 views
11

Tôi có một ArrayAdapter (myAdapter) được đính kèm với một thành phần AutoCompleteTextView (textView).
Khi người dùng nhấn một ký tự, tôi muốn điền danh sách thả xuống của AutoCompleteTextView với các mục chứa ký tự này.
Tôi truy xuất các mục bằng cách sử dụng AsyncTask (sử dụng dịch vụ web).Android, hàm add() của ArrayAdapter không hoạt động

Tôi gọi myAdapter.add (mục) nhưng danh sách thả xuống trống.
Tôi đã thêm một cuộc gọi myAdapter.getCount() sau mỗi lần thêm và nó hiển thị bằng không mọi lúc. Gọi notificationDataSetChanged() không giúp được gì.
Tôi thậm chí đã cố gắng thêm các đối tượng String đơn giản thay vì các đối tượng tùy chỉnh của tôi, không có kết quả.
Tôi đang làm gì sai?

Chỉnh sửa: Tôi đã thay đổi mã như miette được đề xuất bên dưới nhưng vẫn không có kết quả.
Nói chung, những gì tôi làm là sau khi văn bản được thay đổi trong chế độ xem văn bản hoàn toàn tự động của tôi, tôi gọi AsyncTask mới và chuyển nó vào văn bản đã nhập và Trình xử lý (xem afterTextChanged()). Nhiệm vụ truy lục các đối tượng liên quan đến văn bản và một khi đã thực hiện handleMessage() của Handler() được gọi. Trong handleMessage(), tôi cố gắng đưa các đối tượng của adapter. Nhưng danh sách thả xuống của adapter vẫn kết thúc.

Đây là mã của tôi:

public class AddStockView extends Activity 
     implements OnClickListener, OnItemClickListener, TextWatcher { 

    ArrayAdapter<Stock> adapter; 
    AutoCompleteTextView textView; 
    Vector<Stock> stocks; 
    public AddStockView() { 
     // TODO Auto-generated constructor stub 
     stocks = new Vector<Stock>(); 
    } 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.add_stock_view); 

     findViewById(R.id.abort_button).setOnClickListener(this); 

     adapter = new ArrayAdapter<Stock>(this, 
     android.R.layout.simple_dropdown_item_1line, stocks); 
     //adapter.setNotifyOnChange(true); 
     textView = (AutoCompleteTextView) 
     findViewById(R.id.search_edit_text); 
     textView.setAdapter(adapter); 
     textView.setOnItemClickListener(this); 
     textView.addTextChangedListener(this); 

    } 
    @Override 
    public void onClick(View v) { 
     // TODO Auto-generated method stub 
     switch (v.getId()) 
     { 
     case R.id.abort_button: 
     finish(); 
     break; 
     case R.id.search_edit_text: 

     break; 
     } 
    } 
    @Override 
    public void onItemClick(AdapterView<?> parent, View v, 
          int position, long id) { 
     // TODO Auto-generated method stub 
     Stock stockToAdd = (Stock)parent.getAdapter().getItem(position); 
     //TODO: Add the above stock to user's stocks and close this screen 
     finish(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     super.onCreateOptionsMenu(menu); 
     getMenuInflater().inflate(R.layout.menu, menu); 

     CategoryMenu.getInstance().populateMenu(menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     CategoryMenu.getInstance().menuItemSelected(item, this); 
     return false; 
    } 

    @Override 
    public boolean onPrepareOptionsMenu(Menu menu) { 
     return true; 
    } 
    @Override 
    public void afterTextChanged(Editable text) { 
     // TODO Auto-generated method stub 
     if (text.toString().equals("")) 
     return; 
     new AppTask().execute(new AppTask.Payload(Consts.taskType.SEARCH_STOCK, 
              new Object[] {text, handler}, this)); 

    } 
    @Override 
    public void beforeTextChanged(CharSequence a0, int a1, int a2, int a3) { 
     // TODO Auto-generated method stub 
    } 
    @Override 
    public void onTextChanged(CharSequence a0, int a1, int a2, int a3) { 
     // TODO Auto-generated method stub 
    } 
    private void addStockItemsToAdapter(Vector<Object> dataItems) 
    { 
     for (int i = 0; i <dataItems.size(); i++) 
     { 
     Stock stk = (Stock)dataItems.elementAt(i); 
     stocks.add(stk); 
     } 
    } 

    public void populateAdapter() 
    { 
     addStockItemsToAdapter(ContentReader.getInstance.getDataItems());  
     adapter.notifyDataSetChanged(); 
     int size = adapter.getCount(); // size == 0 STILL!!!! 
     textView.showDropDown(); 
    } 
    final Handler handler = new Handler() { 
     public void handleMessage(Message msg) { 
     populateAdapter(); 
     } 
    }; 
} 

Thanks a lot, Rob

Trả lời

0

Nơi nào bạn gọi addItemsToAdapter()? Bạn có thể chỉ cho chúng tôi, cách bạn đã cố gắng thêm các Chuỗi đơn giản vào Bộ điều hợp của mình không?

Chỉnh sửa: hết các ý kiến ​​mẫu mã hữu ích:

adapter = new ArrayAdapter<Stock>(this, android.R.layout.simple_dropdown_item_1line, stocks); 
adapter.notifyDataSetChanged(); 
textView.setAdapter(adapter); 
+0

Đây là những gì tôi đã làm: Tôi định nghĩa một Handler và đặt nó trong AsyncTask của tôi (gọi tắt là AppTask) params như vậy: new AppTask().execute(new AppTask.Payload(Consts.taskType.SEARCH_STOCK, \t \t \t \t new Object[] {text, handler}, this)); Sau đó, trong handleMessage Handler của tôi() Tôi gọi addItemsToAdapter . Đối với các Chuỗi, tôi đã khai báo mảng này: Chuỗi cuối cùng riêng tư [] COUNTRIES = new String [] { "Bỉ", "Pháp", "Ý", "Đức", "Tây Ban Nha" }; và thay vì gọi: myAdapter.add (tmpItem); Tôi đã gọi; myAdapter.add (COUNTRIES [i]) và thậm chí COUNTRIES [0]. Cảm ơn sự giúp đỡ của bạn! – Rob

+0

Có cách nào tôi có thể đăng toàn bộ mã không? – Rob

+0

Bạn có thể tải lên zip dự án tối thiểu ở đâu đó hoặc chỉnh sửa câu hỏi của bạn ở trên và thêm mã ở đó ... – WarrenFaith

2

Tạo một adapter mảng với một vector hoặc mảng như:

ArrayAdapter(Context context, int textViewResourceId, T[] objects) 

Bằng cách khởi tạo arrayadapter của bạn, bạn sẽ làm cho nó nghe đối tượng mảng. Không thêm mục vào bộ điều hợp hoặc xóa bộ điều hợp, thực hiện các bổ sung của bạn trong mảng "đối tượng" và cũng xóa nó. Sau khi thay đổi nào trên mảng này gọi

adapter.notifyDataSetChanged(); 

Cụ thể hơn

ArrayAdapter<YourContentType> yourAdapter = new ArrayAdapter<YourContentType> (this,R.id.OneOfYourTextViews,YourDataList); 

yourAdapter.notifyDataSetChanged();  
aTextView.setText(yourAdapter.isEmpty() ? "List is empty" : "I have too many objects:)"); 

này nên được thực hiện sau khi tải YourDataList, tôi đã kiểm tra mã của bạn, bạn có chắc handler gọi addStockItemsToAdapter() trước khi bạn nhìn adapter của bạn là trống rỗng hay không ? Bạn cũng nên kiểm tra xem vector cổ phiếu có bất kỳ yếu tố nào trong đó không.

+0

Tôi đã làm như bạn đề xuất nhưng nó vẫn không hoạt động. Tôi có một Handler có handleMessage() được gọi khi cấu trúc dữ liệu đến. Trong handleMessage() tôi gọi một hàm lặp qua cấu trúc dữ liệu và thêm các phần tử vào đối tượng T [] của adapter và sau đó gọi adapter.notifyDataSetChanged(). Sau khi tất cả adapter.getCount() này vẫn trả về 0. Nó là cái quái gì vậy? – Rob

+0

Xin chào một lần nữa, tôi đang thay đổi câu trả lời của tôi cho bạn. Tôi đã thử nghiệm những gì bạn muốn làm và nó hoạt động cho tôi. – miette

+0

Hi miette, tôi đánh giá cao bạn nhìn vào điều này. Bạn đang đề xuất giống như Warren và thực sự điều này đã giải quyết được vấn đề. Btw, tôi nhận ra rằng gọi callingDataSetChanged() là dư thừa vì tuyên bố "ArrayAdapter" mới chứa nguồn dữ liệu cập nhật. Tôi nghĩ rằng tôi có thể có nguồn dữ liệu của tôi (YourDataList) trống khi tạo ra các bộ chuyển đổi, thêm các mục vào nó trên đường đi và gọi notifyDataSetChanged() khi thực hiện thêm, nhưng có vẻ như nó không hoạt động, phải không? Dù sao, nhiều nghĩa vụ người đàn ông của tôi. – Rob

12

Tôi gặp vấn đề tương tự. Sau khi kiểm tra mã nguồn ArrayAdapter và AutoCompleteTextView, tôi phát hiện ra rằng vấn đề là, trong ngắn hạn, rằng:

  • danh sách đối tượng gốc được lưu trữ trong ArrayAdapter.mObjects.
  • Tuy nhiên, AutoCompleteTextView bật lọc của ArrayAdapter, nghĩa là các đối tượng mới được thêm vào ArrayAdapter.mOriginalValues, trong khi mObjects chứa các đối tượng được lọc.
  • ArrayAdapter.getCount() luôn trả về kích thước là mObjects.

Giải pháp của tôi là ghi đè ArrayAdapter.getFilter() để trả lại bộ lọc không lọc. Bằng cách này, là nullmObjects được sử dụng thay thế trong mọi trường hợp.

Mẫu mã:

public class MyAdapter extends ArrayAdapter<String> { 
    NoFilter noFilter; 
    /* 
    ... 
    */ 

    /** 
    * Override ArrayAdapter.getFilter() to return our own filtering. 
    */ 
    public Filter getFilter() { 
     if (noFilter == null) { 
      noFilter = new NoFilter(); 
     } 
     return noFilter; 
    } 

    /** 
    * Class which does not perform any filtering. 
    * Filtering is already done by the web service when asking for the list, 
    * so there is no need to do any more as well. 
    * This way, ArrayAdapter.mOriginalValues is not used when calling e.g. 
    * ArrayAdapter.add(), but instead ArrayAdapter.mObjects is updated directly 
    * and methods like getCount() return the expected result. 
    */ 
    private class NoFilter extends Filter { 
     protected FilterResults performFiltering(CharSequence prefix) { 
      return new FilterResults(); 
     } 

     protected void publishResults(CharSequence constraint, 
             FilterResults results) { 
      // Do nothing 
     } 
    } 
} 
+0

BẠN SIR TUYỆT VỜI !!! – Anderson

+0

trong các trường hợp khác, lọc là những gì bạn thực sự cần và bạn có thể sử dụng nó như được giải thích [ở đây] (http://android.foxykeep.com/dev/how-to-add-autocompletion-to-an-edittext) trong Ví dụ về Webservice. – vfede

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