1

アプリでカスタム検索候補を作成しようとしています。ドキュメントと検索可能な辞書の例から始めました。ただし、この例は私にはあまり適していないので、インターネットにもチュートリアルがあまりないため、正確な作成方法を見つけるためにいくつかのテストを開始しました。

通常、私のアプリには現在 2 つのデータベースがあります。1 つは通常のデータベース、もう 1 つは列の数が少ない FTS3 です。私が達成したいのは、提案プロバイダーをこの FTS3 テーブルに接続することです。

私がやろうとしていたのは、単純な関数を使用して、検索ボックスに任意の文字を入力した後、DB 全体 (約 200 レコード) を提案で返すことでした。レコード数が 50 に制限されていることは知っていますが、それが問題だとは思いません。これはプロバイダーのコードの一部です。私が見つけたのは、テキストを入力すると、プロバイダーがオプションに移動すること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 が返されます。

さらに深くなると、いくつかの Log タグも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;
    }

したがって、一般的に言えば、カーソルをDB全体に返す必要がありますが、代わりに、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 に答える