Correct display of SearchView suggestions
I recently added SearchView
to my application (the one listed in the library support-v7
). In my case, the submit button should never start a new one Intent
with ACTION_SEARCH
, I just want to show a list of offers that the user can view and click on one of them triggers some action.
I think everything is set up correctly, but I have two big problems:
- The first time I type something, even though all events are fired (I used some log prints to check this), the suggestion list is not displayed, I need to clear the search text and restart the entry, then the suggestions are shown. This only happens the first time I search for something. If I close and reopen it
SearchView
, it shows suggestions on the first try. - To load suggestions, I request
ContentProvider
throughLoaderManager
, and if I type too fast, the application will crash and say that I am trying to reopen an already closed object (I think the cursor I get by requestingContentProvider
).
What should I change in my code to make it work correctly?
Code:
in onCreateOptionsMenu
:
mActivity.getMenuInflater().inflate(R.menu.itemselect_search, menu);
SearchManager searchManager = (SearchManager) mActivity
.getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.item_search)
.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(mActivity
.getComponentName()));
searchView.setOnQueryTextListener(this);
searchView.setOnSuggestionListener(this);
my onQueryTextListener
:
public boolean onQueryTextSubmit(String query) {
return true;
}
public boolean onQueryTextChange(String newText) {
Log.i("TextChange", "=(" + newText + ")");
if (newText == null || newText.isEmpty()) {
//Empty the suggestions instead of showing all items...
if (null != mSuggestionAdapter)
mSuggestionAdapter.swapCursor(null);
} else {
currentSearchQuery = newText;
mActivity.getSupportLoaderManager().restartLoader(1, null, this);
}
return true;
}
my onCreateLoader
:
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
CursorLoader mCursorLoader = null;
switch (id) {
//Other Loader IDs...
case 1:
Log.i("OnCreateLoader", "Loader created: " + id);
mCursorLoader = new CursorLoader(mActivity,
MyContentProvider.URI,
SQLiteRomDataSource.allColumns,
mSelection,
mSelectionArgs, null);
break;
}
return mCursorLoader;
}
my onLoadFinished
:
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
switch (loader.getId()) {
//Other Loader IDs...
case 1:
Log.i("OnLoadFinished",
"Loader " + loader.getId() + ", " + cursor.getCount()
+ " results");
if (null == mSuggestionAdapter) {
Log.i("OnLoadFinished","Creating adapter");
mSuggestionAdapter = new SuggestionsCursorAdapter(
mActivity, cursor, 0);
}
if (searchView.getSuggestionsAdapter() != mSuggestionAdapter){
Log.i("OnLoadFinished","Binding adapter to searchview");
searchView.setSuggestionsAdapter(mSuggestionAdapter);
}
mSuggestionAdapter.swapCursor(cursor);
Log.i("OnLoadFinished","Swapping cursor...");
break;
}
}
And finally mine onLoaderReset
:
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
//Other Loader IDs...
case 1:
mSuggestionAdapter.swapCursor(null);
break;
}
}
source to share
After further testing, I decided not to use LoaderManager
and do everything inside my method onQueryTextChange
. Both problems seem to be resolved.
public boolean onQueryTextChange(String newText) {
Log.i("TextChange", "=(" + newText + ")");
if (newText == null || newText.isEmpty()) {
if (null != mSuggestionAdapter)
mSuggestionAdapter.swapCursor(null);
} else {
Cursor mCur = mActivity.getContentResolver().query(
MyContentProvider.URI,
DataSource.allColumns,
mSelection, mSelectionArgs, null);
if(null == mRomSuggestionAdapter){
mRomSuggestionAdapter = new SuggestionsCursorAdapter(mActivity,mCur,0);
searchView.setSuggestionsAdapter(mRomSuggestionAdapter);
}
if (null != mSuggestionAdapter)
mSuggestionAdapter.swapCursor(mCur);
}
return true;
}
source to share