I have an ArrayAdapter (myAdapter) attached to an AutoCompleteTextView (textView) component.
Once the user presses a character I would like to populate AutoCompleteTextView's drop down list with items containing this character.
I retrieve the items using AsyncTask (which uses a web service).
I call myAdapter.add(item) but the drop down list is empty.
I added a call myAdapter.getCount() after each addition and it shows zero every time.
Calling notifyDataSetChanged() didn't help.
I even tried to add simple String objects instead of my custom objects, to no avail.
What am I doing wrong?
Edit: I changed the code as miette suggested below but still to no avail.
Generally, what I do is after text is changed in my auto complete text view, I call a new AsyncTask and pass it the entered text and a Handler (see afterTextChanged()). The task retrieves objects relevant to the text and once done the Handler's handleMessage() is called. In handleMessage() I attempt to populate the adapter's objects. But still the adapter's drop down list ends up empty.
Here is my code:
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
Create a global ArrayList and add the contents to it using add() and pass it to ArrayAdapter. It's better to pass the List or String[] to ArrayAdapter and set that adapter to List You should update the List or Array being passed to Adapter, not Adapter itself.
This example demonstrates how do I dynamically update a ListView in android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.
I had the exact same problem. After examining the ArrayAdapter and AutoCompleteTextView source code, I found out that the problem was, in short, that:
ArrayAdapter.mObjects
.AutoCompleteTextView
enables ArrayAdapter
's filtering, meaning that new objects are added to ArrayAdapter.mOriginalValues
, while mObjects
contains the filtered objects.ArrayAdapter.getCount()
always returns the size of mObjects
.My solution was to override ArrayAdapter.getFilter()
to return a non-filtering filter. This way mOriginalValues
is null
and mObjects
is used instead in all cases.
Sample code:
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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With