为搜索建议实现自己的 Android CursorAdapter - 未知异常
Implementing own Android CursorAdapter for search suggestions - unknown exceptions
我已经实现了自己的游标适配器来手动处理建议,这样我就可以摆脱 android 文档建议的矫枉过正的方法。
基本上我所做的是在操作栏搜索视图被膨胀后将 setOnQueryTextListener 设置到它。每次用户输入新的搜索文本时,我都会查询一个 returns 游标的 Sqlite 数据库。最后,我使用检索到的游标创建了我自己的游标适配器,并使用 setSuggestionsAdapter 方法将其设置为搜索视图。
这里的问题是,根据每次配置更改时更新光标的方式,我会收到许多未知异常。我稍后解释,首先是一些代码:
*************************** 我自己的光标适配器 class ************ ************
public class BusStopCursorAdapter 扩展了 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;
}
}
************************ 添加到搜索视图的侦听器 **************** ***
// 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;
}
});
在这种情况下,我更新游标所做的就是彻底添加一个全新的适配器。一开始一切顺利,但是当发生配置更改时,我得到了这个日志:
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
应用程序似乎运行良好。唯一无法解释的问题(可能与这些异常有关)是在配置更改后有时会出现建议,有时不会。就像它无法执行查询之类的。
例如,如果我使用这个仅更新光标的替代侦听器实现(因为它应该是最干净的方式)而不是重新创建整个适配器,事情会变得更糟:我得到未知的 SQL 错误( sql 查询工作正常时不应该存在),某种游标列访问错误(显示建议时不应该存在)并且应用程序最终崩溃。
*************************** 备选侦听器****************** *******************
@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;
}
****************************** 崩溃日志************ *********************
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
我将不胜感激一些帮助,因为我在花费数小时的搜索后完全陷入困境。提前致谢。
你把这个复杂化了:不需要 setOnQueryTextListener,只需调用:
myCursorAdapter.setFilterQueryProvider(this);
searchView.setSuggestionsAdapter(myCursorAdapter);
在 onCreateOptionsMenu
中,您需要 Activity 来实施 FilterQueryProvider
,其中 runQuery
您 return 您的 Cursor
以及建议
刚刚试过了。它就像一个魅力。查询正在处理配置更改并且不再崩溃。唯一的问题是每次配置更改时我都会在 logcat 中收到这些异常:
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
我已经实现了自己的游标适配器来手动处理建议,这样我就可以摆脱 android 文档建议的矫枉过正的方法。 基本上我所做的是在操作栏搜索视图被膨胀后将 setOnQueryTextListener 设置到它。每次用户输入新的搜索文本时,我都会查询一个 returns 游标的 Sqlite 数据库。最后,我使用检索到的游标创建了我自己的游标适配器,并使用 setSuggestionsAdapter 方法将其设置为搜索视图。 这里的问题是,根据每次配置更改时更新光标的方式,我会收到许多未知异常。我稍后解释,首先是一些代码:
*************************** 我自己的光标适配器 class ************ ************
public class BusStopCursorAdapter 扩展了 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;
}
}
************************ 添加到搜索视图的侦听器 **************** ***
// 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;
}
});
在这种情况下,我更新游标所做的就是彻底添加一个全新的适配器。一开始一切顺利,但是当发生配置更改时,我得到了这个日志:
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
应用程序似乎运行良好。唯一无法解释的问题(可能与这些异常有关)是在配置更改后有时会出现建议,有时不会。就像它无法执行查询之类的。
例如,如果我使用这个仅更新光标的替代侦听器实现(因为它应该是最干净的方式)而不是重新创建整个适配器,事情会变得更糟:我得到未知的 SQL 错误( sql 查询工作正常时不应该存在),某种游标列访问错误(显示建议时不应该存在)并且应用程序最终崩溃。
*************************** 备选侦听器****************** *******************
@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;
}
****************************** 崩溃日志************ *********************
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
我将不胜感激一些帮助,因为我在花费数小时的搜索后完全陷入困境。提前致谢。
你把这个复杂化了:不需要 setOnQueryTextListener,只需调用:
myCursorAdapter.setFilterQueryProvider(this);
searchView.setSuggestionsAdapter(myCursorAdapter);
在 onCreateOptionsMenu
中,您需要 Activity 来实施 FilterQueryProvider
,其中 runQuery
您 return 您的 Cursor
以及建议
刚刚试过了。它就像一个魅力。查询正在处理配置更改并且不再崩溃。唯一的问题是每次配置更改时我都会在 logcat 中收到这些异常:
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