问题
I have implemented my own cursor adapter to manually handle suggestions, so that I can get rid of the overkill method that android docs proposes. Basically what I do is setOnQueryTextListener to the actionbar searchview after it's been inflated. Everytime the user inputs a new search text, I query a Sqlite db which returns a cursor. Finally, I create my own cursor adapter with the retrieved cursor and set it to the searchview with setSuggestionsAdapter method. The problem here is that I am getting many unknown exceptions depending on the way I update the cursor everytime the config changes. I'exaplin it later, first some code:
************************ My own cursor adapter class ************************
public class BusStopCursorAdapter extends CursorAdapter {
public BusStopCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
//set address
((TextView)view.findViewById(R.id.address)).setText(cursor.getString(1));
//set line
((TextView)view.findViewById(R.id.line)).setText(cursor.getString(2));
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.suggestions_layout, parent, false);
//set address
((TextView)view.findViewById(R.id.address)).setText(cursor.getString(1));
//set line
((TextView)view.findViewById(R.id.line)).setText(cursor.getString(2));
return view;
}
}
*********************** the listener added to the searchView *******************
// Associate searchView listeners
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
System.out.println("QUERY STRING: "+newText);
Cursor cursor = queryData(newText);
searchView.setSuggestionsAdapter(new BusStopCursorAdapter(getBaseContext(), cursor));
return true;
}
});
In this case, what I do to update the cursor is drastically add a brand new adapter. At first everything goes well, but when a config change happens I get this log:
03-10 15:20:11.762 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING: ad
03-10 15:20:13.012 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING: ado
03-10 15:20:13.992 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING: adol
03-10 15:20:15.602 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING:
03-10 15:20:15.602 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING: adol
03-10 15:20:15.662 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
03-10 15:20:15.672 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
03-10 15:20:15.722 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:20:15.812 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:20:15.882 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
03-10 15:20:18.402 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING:
03-10 15:20:18.402 1927-1927/com.nikkis.vallabus I/System.out﹕ QUERY STRING: adol
03-10 15:20:18.492 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
03-10 15:20:18.492 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
03-10 15:20:18.522 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:20:18.552 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:20:18.592 1927-1927/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
The application seems to work fine. The only unexplainable issue (probably regarding to these exceptions) is that after a config change sometimes the suggestions appear and sometimes dont. Is like if it couldnt perform the query or something.
If for example I use this alternative listener implementation which updates just the cursor (as it should be the cleanest way) instead of recreating the whole adapter the thing gets even worse: I get unknown SQL error (which shouldnt be there as the sql query works perfeclty), some kind of cursor column access error(either shouldnt be there as the suggestions are being shown) and the app eventually crashes.
************************* Alternative listener**********************************
@Override
public boolean onQueryTextChange(String newText) {
System.out.println("QUERY STRING: "+newText);
Cursor cursor = queryData(newText);
/* if (newText !="")
searchView.setSuggestionsAdapter(new BusStopCursorAdapter(getBaseContext(), cursor));*/
if (searchView.getSuggestionsAdapter() == null) {
searchView.setSuggestionsAdapter(new BusStopCursorAdapter(getBaseContext(), cursor));
} else {
searchView.getSuggestionsAdapter().changeCursor(cursor);
}
return true;
}
****************************** the crashing log*********************************
03-10 15:58:46.762 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:58:46.792 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
03-10 15:58:48.612 3767-3767/com.nikkis.vallabus I/System.out﹕ QUERY STRING:
03-10 15:58:48.622 3767-3767/com.nikkis.vallabus I/System.out﹕ QUERY STRING: adol
03-10 15:58:48.632 3767-4304/com.nikkis.vallabus W/Filter﹕ An exception occured during performFiltering()!
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteQuery: SELECT stop.stopID AS _id, stop.address, stop_line.line FROM stop_line, stop WHERE stop.stopID = stop_line.stop AND stop.address LIKE '%%';
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:58)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.widget.CursorFilter.performFiltering(CursorFilter.java:53)
at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:213)
at android.os.HandlerThread.run(HandlerThread.java:60)
03-10 15:58:48.652 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
03-10 15:58:48.652 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
03-10 15:58:48.652 3767-4304/com.nikkis.vallabus E/CursorWindow﹕ Failed to read row 0, column 0 from a CursorWindow which has 1 rows, 0 columns.
03-10 15:58:48.702 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:58:48.792 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 15:58:48.832 3767-3767/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
I would appreciate some help as I am completely stuck after spending hours of searching. Thanks in advance.
回答1:
you have over-complicated this: there is no need for setOnQueryTextListener, just call:
myCursorAdapter.setFilterQueryProvider(this);
searchView.setSuggestionsAdapter(myCursorAdapter);
in onCreateOptionsMenu
, you will need your Activity to implement FilterQueryProvider
where in its runQuery
you return your Cursor
with suggestions
回答2:
Just tried it. It works like a charm. The query is working on config changes and it doesnt crash anymore. The only issue is that I am getting these exceptions in logcat everytime the config changes:
03-10 19:39:06.542 30711-30711/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 19:39:06.622 30711-30711/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
03-10 19:39:06.672 30711-30711/com.nikkis.vallabus W/IInputConnectionWrapper﹕ getExtractedText on inactive InputConnection
03-10 19:39:08.252 30711-30711/com.nikkis.vallabus W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
来源:https://stackoverflow.com/questions/28967136/implementing-own-android-cursoradapter-for-search-suggestions-unknown-exceptio