【问题标题】:Implementing own Android CursorAdapter for search suggestions - unknown exceptions为搜索建议实现自己的 Android CursorAdapter - 未知异常
【发布时间】:2015-03-10 15:03:18
【问题描述】:

我已经实现了自己的光标适配器来手动处理建议,这样我就可以摆脱 android 文档提出的过度杀伤方法。 基本上我所做的是在操作栏搜索视图被充气后将其设置为 setOnQueryTextListener。每次用户输入新的搜索文本时,我都会查询一个返回游标的 Sqlite 数据库。最后,我使用检索到的光标创建自己的光标适配器,并使用 setSuggestionsAdapter 方法将其设置为搜索视图。 这里的问题是我得到了许多未知的异常,这取决于我每次配置更改时更新光标的方式。我稍后再解释,首先是一些代码:

************************ 我自己的游标适配器类 ****************** ******

公共类 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;

}
}

************************ 添加到 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;
        }
    });

在这种情况下,我更新光标的方法是彻底添加一个全新的适配器。起初一切顺利,但当配置更改发生时,我会收到以下日志:

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

我很感激一些帮助,因为我在花费数小时搜索后完全陷入困境。提前致谢。

【问题讨论】:

  • 调用 setSuggestionsAdapter ONCE 并在该适配器中设置 FilterQueryProvider
  • 您也不需要任何 setOnQueryTextListener:只需在 onCreateOptionsMenu 中调用 setSuggestionsAdapter() 一次即可
  • 感谢您的 anser pskink,但我想我错过了它的工作原理。我的猜测是: 1. 您通过 setOnQueryTextListener 收到一个新的输入文本。 2. 您使用该文本查询数据库。 3. 数据库将您更改的游标返回到适配器。 4. 建议列表视图得到更新。这种方式是如何工作的?因为我不明白为什么它会失败。那个 FilterQueryProvider 是干什么用的?
  • 不,不需要setOnQueryTextListener,只需要在onCreateOptionsMenu中调用myAdapter.setFilterQueryProvider(this)和searchView.setSuggestionsAdapter(myAdapter)
  • myAdapter 可以只是 SimpleCursorAdapter,不需要自定义

标签: java android sqlite searchview android-cursoradapter


【解决方案1】:

你过于复杂了:不需要 setOnQueryTextListener,只需调用:

myCursorAdapter.setFilterQueryProvider(this);
searchView.setSuggestionsAdapter(myCursorAdapter);

onCreateOptionsMenu 中,您将需要您的 Activity 来实施 FilterQueryProvider,在其 runQuery 中您返回您的 Cursor 并提供建议

【讨论】:

    【解决方案2】:

    刚刚试了一下。它就像一个魅力。该查询正在处理配置更改,并且不再崩溃。唯一的问题是每次配置更改时我都会在 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
    

    【讨论】:

    • 不知道它是什么……是你的吗? com.nikkis.vallabus?
    • 即应用包名。
    • 你还在用 OnQueryTextListener 吗?
    • 不,我已经删除了。不知道可以是什么。可能是因为扩展 CursorAdapter 时缺少某些东西。
    • 我不知道,从未见过这样的警告,可以肯定的是,出于测试目的尝试 SimpleCursorAdapter
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多