I have a list of countries in a database. I have created a select country activity that consists of a edit box for filtering and a list which displays the flag and country name.
When the activity starts the list shows the entire list of countries sorted alphabetically - works fine. When the customer starts typing into the search box I want the list to be filtered based on their typing. My database query was previously working in an AutoCompleteView (I just want to switch to a separate text box and list) so I know my full query and my constraint query are working. What I did was add a TextWatcher to the EditText view and every time the text is changed I invoke the list's SimpleCursorAdapter runQueryOnBackgroundThread with the edit boxes text as the constraint. The trouble is the list is never updated. I have set breakpoints in the debugger and the TextWatcher does make the call to runQueryOnBackgroundThread and my FilterQueryProvider is called with the expected constraint. The database query goes fine and the cursor is returned.
The cursor adapter has a filter query provider set (and a view binder to display the flag):
SimpleCursorAdapter adapter = new SimpleCursorAdapter (this,
R.layout.country_list_row, countryCursor, from, to);
adapter.setFilterQueryProvider (new CountryFilterProvider ());
adapter.setViewBinder (new FlagViewBinder ());
The FitlerQueryProvider:
private final class CountryFilterProvider implements FilterQueryProvider {
@Override
public Cursor runQuery (CharSequence constraint) {
Cursor countryCursor = myDbHelper.getCountryList (constraint);
startManagingCursor (countryCursor);
return countryCursor;
}
}
And the EditText has a TextWatcher:
myCountrySearchText = (EditText)findViewById (R.id.entry);
myCountrySearchText.setHint (R.string.country_hint);
myCountrySearchText.addTextChangedListener (new TextWatcher() {
@Override
public void afterTextChanged (Editable s) {
SimpleCursorAdapter filterAdapter = (SimpleCursorAdapter)myCountryList.getAdapter ();
filterAdapter.runQueryOnBackgroundThread (s.toString ());
}
@Override
public void onTextChanged (CharSequence s, int start, int before, int count) {
// no work to do
}
@Override
public void beforeTextChanged (CharSequence s, int start, int count, int after) {
// no work to do
}
});
The query for the database looks like this:
public Cursor getCountryList (CharSequence constraint) {
if (constraint == null || constraint.length () == 0) {
// Return the full list of countries
return myDataBase.query (DATABASE_COUNTRY_TABLE,
new String[] { KEY_ROWID, KEY_COUNTRYNAME, KEY_COUNTRYCODE }, null, null, null,
null, KEY_COUNTRYNAME);
} else {
// Return a list of countries who's name contains the passed in constraint
return myDataBase.query (DATABASE_COUNTRY_TABLE,
new String[] { KEY_ROWID, KEY_COUNTRYNAME, KEY_COUNTRYCODE },
"Country like '%" + constraint.toString () + "%'", null, null, null,
"CASE WHEN Country like '" + constraint.toString () +
"%' THEN 0 ELSE 1 END, Country");
}
}
It just seems like there is a missing link somewhere. Any help would be appreciated.
Thanks,
Ian
I saw that you managed to solve your problem in another way, but thought I should add the answer for other people stumbling upon this question.
runQueryOnBackgroundThread() is only responsible for running a query for a constraint and returning a Cursor. To be able to filter the adapter based on the cursor you need to do something like
filterAdapter.getFilter().filter(s.toString());
A CursorAdapter always implements Filterable by default, and anything that implements filterable can be filtered using
getFilter().filter(constraint)
The way that the CursorAdapters built in filter works is that if you either override runQueryOnBackgroundThread() or if you use setFilterQueryProvider() then it runs that code in a background thread, gets a new cursor and sets it as the cursor of the CursorAdapter.
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