【问题标题】:Android, add() function of ArrayAdapter not workingAndroid,ArrayAdapter 的 add() 函数不起作用
【发布时间】:2010-03-01 13:33:07
【问题描述】:

我有一个附加到 AutoCompleteTextView (textView) 组件的 ArrayAdapter (myAdapter)。
一旦用户按下一个字符,我想用包含该字符的项目填充 AutoCompleteTextView 的下拉列表。
我使用 AsyncTask(使用 Web 服务)检索项目。

我调用 myAdapter.add(item) 但下拉列表为空。
我在每次添加后添加了一个调用 myAdapter.getCount() ,每次都显示为零。 调用 notifyDataSetChanged() 没有帮助。
我什至尝试添加简单的 String 对象而不是我的自定义对象,但无济于事。
我究竟做错了什么?

编辑:我按照 miette 下面的建议更改了代码,但仍然无济于事。
通常,我所做的是在我的自动完成文本视图中更改文本后,我调用一个新的 AsyncTask 并将输入的文本和一个处理程序传递给它(参见 afterTextChanged())。该任务检索与文本相关的对象,一旦完成,就会调用 Handler 的 handleMessage()。在 handleMessage() 中,我尝试填充适配器的对象。但是适配器的下拉列表仍然是空的。

这是我的代码:

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();
      }
    };
}

非常感谢,罗伯

【问题讨论】:

    标签: android


    【解决方案1】:

    我遇到了完全相同的问题。在检查了 ArrayAdapter 和 AutoCompleteTextView 的源代码后,我发现问题在于:

    • 原始对象列表存储在ArrayAdapter.mObjects
    • 但是,AutoCompleteTextView 启用ArrayAdapter 的过滤,这意味着新对象将添加到ArrayAdapter.mOriginalValues,而mObjects 包含过滤后的对象。
    • ArrayAdapter.getCount() 始终返回 mObjects 的大小。

    我的解决方案是覆盖 ArrayAdapter.getFilter() 以返回非过滤过滤器。这样mOriginalValues 就是nullmObjects 在所有情况下都使用。

    示例代码:

    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
            }
        }
    }
    

    【讨论】:

    • 在其他情况下,过滤是您真正需要的,您可以按照 Webservice 示例中here 的说明使用它。
    【解决方案2】:

    使用向量或数组创建数组适配器,例如:

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

    通过初始化你的arrayadapter,你可以让它监听objects 数组。不要将项目添加到适配器或清除适配器,在“对象”数组中添加并清除它。更改此数组调用后

    adapter.notifyDataSetChanged();
    

    更具体

    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:)");
    

    这应该在加载 YourDataList 后完成,我检查了你的代码,你确定处理程序调用 addStockItemsToAdapter() 在你查看适配器是否为空之前? 您还应该检查 stock 向量中是否包含任何元素。

    【讨论】:

    • 我按照你的建议做了,但还是不行。我有一个处理程序,一旦数据结构到达,它的 handleMessage() 就会被调用。在handleMessage() 中,我调用了一个函数,它遍历数据结构并将元素添加到适配器的T[] 对象,然后调用adapter.notifyDataSetChanged()。毕竟这个 adapter.getCount() 仍然返回零。到底是什么鬼?
    • 您好,我正在为您更改答案。我已经测试了你想要做什么,它对我有用。
    • 您好 miette,感谢您对此进行调查。你的建议和沃伦一样,这确实解决了问题。顺便说一句,我意识到现在调用 notifyDataSetChanged() 是多余的,因为“new ArrayAdapter”语句包含更新的数据源。我想我可以在创建适配器时让我的数据源(YourDataList)为空,沿途添加项目并在完成添加时调用 notifyDataSetChanged(),但它似乎不起作用,是吗?无论如何,非常感谢我的男人。
    • 实际上沿途添加项目一定是有效的。要查看此操作,我可以建议调用 YourDataList.clear() 并手动对 YourDataList 进行一些添加,例如单击虚拟按钮然后调用 notifyDataSetChanged() 时,它必须以这种方式工作。
    【解决方案3】:

    你在哪里调用 addItemsToAdapter()? 您能告诉我们,您是如何尝试向适配器添加简单字符串的吗?

    编辑:在 cmets 中有用的代码示例:

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

    【讨论】:

    • 这就是我所做的:我定义了一个处理程序并将其放入我的 AsyncTask(称为 AppTask)参数中,如下所示: new AppTask().execute(new AppTask.Payload(Consts.taskType. SEARCH_STOCK, new Object[] {text, handler}, this)); 然后,在我的 Handler 的 handleMessage() 中,我调用了 addItemsToAdapter。至于字符串,我声明了这个数组: private static final String[] COUNTRIES = new String[] { "Belgium", "France", "Italy", "Germany", "Spain" };而不是调用: myAdapter.add(tmpItem);我打了电话; myAdapter.add(COUNTRIES[i]) 甚至 COUNTRIES[0]。感谢您的帮助!
    • 您可以在某处上传一个简约的项目 zip 或在上面编辑您的问题并在那里添加代码...
    • 嗯...我只有一个猜测:ContentReader.getInstance.getDataItems() 为空...您是否尝试过使用一些 Log 语句来查看某些值或更好,您是否尝试过调试你的申请?
    • 数据项在那里。在调试期间,我可以看到数据项(在本例中为股票信息)结构中填充了相关项。我还看到每只股票都被添加到 Vector 股票中......
    • hm...上次我在微调器上遇到这样的问题时,我用新数据(在你的情况下是新库存)重新创建了适配器:adapter = new ArrayAdapter(this , android.R.layout.simple_dropdown_item_1line, 股票);适配器.notifyDataSetChanged(); textView.setAdapter(适配器);这对我有帮助...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-30
    • 2021-12-16
    • 2012-05-03
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多