1

我正在尝试在我的应用程序中提出自定义搜索建议。我从文档和可搜索字典示例开始。然而,这个例子对我来说不是很好,所以我已经开始进行一些测试以了解如何制作它,因为互联网上也没有太多的教程。

一般来说,我的应用程序现在有 2 个数据库——一个是正常的,第二个是列数较少的——FTS3。我想要实现的是将建议提供者连接到这个 FTS3 表。

我现在想做的是,使用简单的功能,在搜索框中输入任何字母后,在建议中返回整个数据库(大约 200 条记录)。我知道限制 50 条记录,但我认为这不是问题。这是 Provider 代码的片段。我发现,当您输入文本时,提供者会转到选项SEARCH_SUGGEST

// UriMatcher stuff
    private static final int SEARCH_WORDS = 0;
    private static final int GET_WORD = 1;
    private static final int SEARCH_SUGGEST = 2;
    private static final int REFRESH_SHORTCUT = 3;
    private static final UriMatcher mUriMatcher = buildUriMatcher();

    /**
     * Builds up a UriMatcher for search suggestion and shortcut refresh queries.
     */
    private static UriMatcher buildUriMatcher() {
        Log.d(TAG,"urimatcher");
        UriMatcher matcher =  new UriMatcher(UriMatcher.NO_MATCH);
        // to get definitions...
        matcher.addURI(AUTHORITY, "mydb", SEARCH_WORDS);
        matcher.addURI(AUTHORITY, "mydb/#", GET_WORD);
        // to get suggestions...
        matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
        matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);

        return matcher;
    }

@Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

switch (mUriMatcher.match(uri)) {
            case SEARCH_SUGGEST:
                Log.d(TAG,"SEARCH_SUGGEST");
                if (selectionArgs == null) {
                  throw new IllegalArgumentException(
                      "selectionArgs must be provided for the Uri: " + uri);
                }
                return getSuggestions(selectionArgs[0]);
            case SEARCH_WORDS:
                Log.d(TAG,"SEARCH_WORDS");
                if (selectionArgs == null) {
                  throw new IllegalArgumentException(
                      "selectionArgs must be provided for the Uri: " + uri);
                }
                return search(selectionArgs[0]);
            case GET_WORD:
                Log.d(TAG,"GET_WORD");
                return null;
            default:
                Log.d(TAG,"default");
                throw new IllegalArgumentException("Unknown Uri: " + uri);
        }
    }

private Cursor getSuggestions(String query) {
        String[] columns = { MyDBAdapter.KEY_TITLE,MyDBAdapter.KEY_ID};
              Log.d(TAG,"query1: " + query);

              try{
                  Cursor tmp = MyDB.getAllEntriesFTS(false, columns,
                        null, null, null, null, MyDBAdapter.KEY_TITLE, null, query);
              Log.d(TAG,"cursor: " + Integer.toString(tmp.getCount()));
              }
              catch(Exception e)
              {
                  Log.d(TAG,e.toString());
              }
              return tmp;
    }

getSuggestions我输入的代码通常应该可以工作,但它没有。仅在此处使用时不起作用。当我在其他活动中使用它来获取列表视图的光标时,一切都很好。在这里它返回我的 NullPointerException。

所以越来越深入,我还在方法中添加了一些日志标签getAllEntriesFTS,这个方法看起来像这样:

public Cursor getAllEntriesFTS(boolean distinct, String[] result_columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit, String query) {

        Log.d(TAG,"query db: " + query);

        String[] columns = { MyDBAdapter.KEY_TITLE, MyDBAdapter.KEY_ID};

        Log.d(TAG,"columns: " + Integer.toString(result_columns.length));

        Cursor allRows = null;
        try{
allRows = db.query(distinct, DATABASE_TABLE_FTS, columns,
                    null, null, null, null, MyDBAdapter.KEY_TITLE, null);
            Log.d(TAG,"OK");
        }
        catch(Exception e)
        {
            Log.d(TAG, e.toString());//it always goes there with NullPointerExceptionwhen used in provider
        }
        Log.d(TAG,Integer.toString(allRows.getCount()));
        return allRows;
    }

所以,一般来说,它应该将光标返回到整个数据库,而是在不应该出现 NullPointerException 的地方抛出。

有人可以告诉我我做错了什么以及应该怎么做?

4

1 回答 1

0

感谢 JB Nizet,我能够找到我的错误。我以为我已经很好地研究了谷歌的例子,但我错了。

问题是在游标调用之前没有打开数据库。它应该如下所示:

private Cursor getSuggestions(String query) {
        String[] columns = { MyDBAdapter.KEY_TITLE,MyDBAdapter.KEY_ID};
              Log.d(TAG,"query1: " + query);

              try{
                  MyDB.open();
                  Cursor tmp = MyDB.getAllEntriesFTS(false, columns,
                        null, null, null, null, MyDBAdapter.KEY_TITLE, null, query);
                  MyDB.close();
              Log.d(TAG,"cursor: " + Integer.toString(tmp.getCount()));
              }
              catch(Exception e)
              {
                  Log.d(TAG,e.toString());
              }
              return tmp;
    }

谢谢大家给我看。

于 2013-01-01T22:24:00.333 回答