OnQueryTextChange和LoaderManager,如何管理查询游标?

时间:2013-06-07 01:24:59

标签: search android-contentprovider search-suggestion

我有一个字典的应用程序。在onStart方法中,FragmentActivity调用加载器并填充ListFragment,其中可以看到具有定义的单词。

在那之前一切都很好,但是当我在SearchView上放任何字母时,应用就会停止。

我知道我的应用程序内部的建议路径无效。我几乎打赌它是提供者的getSuggestions游标,与数据库上的queryForWordsMatchesSuggestions连接。

我没有使用SearchManager,因为我不确定是否有必要。无论如何,我的光标如何查询数据库以获取建议而不是app colapsing?

我应该在保存加载器的FragmentActivity上构建另一个游标,还是仅仅通过在提供程序中使用正确的游标就足够了?

感谢。

我将把所有建议路由跳转的代码放在有助于接收答案的例子中。

建议路径是这样的:SearchView正在实现OnQueryText更改,正如您在代码段中看到的那样:

@Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

       MenuItem item = menu.add("Search");
       item.setIcon(android.R.drawable.ic_menu_search);
       item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM );
       SearchView sv = new SearchView(getActivity());
       sv.setOnQueryTextListener(this);
       item.setActionView(sv);
    }

    public boolean onQueryTextChange(String newText) {
        String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
        if (mCurFilter == null && newFilter == null) {
            return true;
        }
        if (mCurFilter != null && mCurFilter.equals(newFilter)) {
            return true;
        }
        mCurFilter = newFilter;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

然后,loadermanager注意,调用CONTENT_URI

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri baseUri;
        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(DictionaryProvider.CONTENT_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = DictionaryProvider.CONTENT_URI; // Why is this not working?
        }

        String select = "((" + DictionaryDatabase.KEY_WORD + " NOTNULL) AND (" 
                             + DictionaryDatabase.KEY_WORD + " != '' ))";

        return new CursorLoader(getActivity(), 
                baseUri,
                DICTIONARY_PROJECTION, 
                select, 
                null, // Select arguments
                DictionaryDatabase.KEY_WORD + " COLLATE LOCALIZED ASC");
    }

然后,提供者来了。 (我取出了游标getWordsArray和getWord,插入,删除和更新相同)

public class DictionaryProvider extends ContentProvider {
private static final String TAG = "DictionaryProvider";

public static String AUTHORITY = "com.dominicapps.cursorsayouno.DictionaryProvider";
public static final Uri CONTENT_URI = Uri.parse(
                                "content://" + AUTHORITY + "/dictionary");

public static final String WORDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +
                                              "/vnd.com.dominicapps.cursorsayouno";
public static final String DEFINITION_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE +
                                                   "/vnd.com.dominicapps.cursorsayouno";

private DictionaryDatabase mDictionary;

private static final int GET_WORDS_ARRAY = 0;
private static final int GET_WORD = 1;
private static final int SUGGESTIONS = 2; // Is this needed?
private static final UriMatcher sURIMatcher = buildUriMatcher();

private static UriMatcher buildUriMatcher() {
    UriMatcher matcher =  new UriMatcher(UriMatcher.NO_MATCH);
    matcher.addURI(AUTHORITY, "dictionary", GET_WORDS_ARRAY);
    matcher.addURI(AUTHORITY, "dictionary/#", GET_WORD);
    matcher.addURI(AUTHORITY, "/*", SUGGESTIONS); 
    return matcher;
}

@Override
public boolean onCreate() {
    mDictionary = new DictionaryDatabase(getContext());
    return true;
}

@Override
public Cursor query(Uri uri, 
                    String[] projection, 
                    String selection, 
                    String[] selectionArgs,
                    String sortOrder) {
    switch (sURIMatcher.match(uri)) {
        case GET_WORDS_ARRAY:
                return getWordsArray(selection);
        case GET_WORD:
            return getWord(uri);
        case SUGGESTIONS:
            if (selectionArgs == null) {
                throw new IllegalArgumentException(
                    "selectionArgs must be provided for the Uri: " + uri);
            }
            return getSuggestions(selectionArgs[0]);    
        default:
            throw new IllegalArgumentException("Unknown Uri: " + uri);
    }
}

private Cursor getSuggestions(String query) {
    String[] columns = new String[] {
      BaseColumns._ID,
      DictionaryDatabase.KEY_WORD,
      DictionaryDatabase.KEY_DEFINITION };      
  return mDictionary.queryForWordMatchesSuggestions(query, columns);
}

@Override
public String getType(Uri uri) {
    switch (sURIMatcher.match(uri)) {
        case GET_WORDS_ARRAY:
            return WORDS_MIME_TYPE;
        case GET_WORD:
            return DEFINITION_MIME_TYPE;
        default:
            throw new IllegalArgumentException("Unknown URL " + uri);
    }
}

这是数据库中的查询光标。

public Cursor queryForWordMatchesSuggestions(String query, String[] columns) {
    String selection = " rowid = ?"; 
    String[] selectionArgs = new String[] {query+"*"};

    return query(selection, selectionArgs, columns);
}

对数据库的一般查询:

public Cursor query(String selection, String[] selectionArgs, String[] columns) {
    Log.d(TAG, "+++ query en Proceso +++");
    SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
    builder.setTables(FTS_VIRTUAL_TABLE);
    builder.setProjectionMap(mColumnMap);

    Cursor cursor = builder.query(mDatabaseOpenHelper.getReadableDatabase(),
            columns, selection, selectionArgs, null, null, null);

    if (cursor == null) {
        return null;
    } else if (!cursor.moveToFirst()) {
        cursor.close();
        return null;
    }
    return cursor;

}

而且,这是日志:

06-17 05:31:55.576: W/dalvikvm(597): threadid=12: thread exiting with uncaught exception (group=0x409c01f8)
06-17 05:31:55.587: E/AndroidRuntime(597): FATAL EXCEPTION: AsyncTask #2
06-17 05:31:55.587: E/AndroidRuntime(597): java.lang.RuntimeException: An error occured while executing doInBackground()
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.os.AsyncTask$3.done(AsyncTask.java:278)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.FutureTask.run(FutureTask.java:137)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.lang.Thread.run(Thread.java:856)
06-17 05:31:55.587: E/AndroidRuntime(597): Caused by: java.lang.IllegalArgumentException: Unknown Uri: content://com.dominicapps.cursorsayouno.DictionaryProvider/dictionary/y
06-17 05:31:55.587: E/AndroidRuntime(597):  at com.dominicapps.cursorsayouno.DictionaryProvider.query(DictionaryProvider.java:65)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.ContentProvider$Transport.query(ContentProvider.java:178)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.ContentResolver.query(ContentResolver.java:311)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.CursorLoader.loadInBackground(CursorLoader.java:56)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.CursorLoader.loadInBackground(CursorLoader.java:42)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:255)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:66)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:55)
06-17 05:31:55.587: E/AndroidRuntime(597):  at android.os.AsyncTask$2.call(AsyncTask.java:264)
06-17 05:31:55.587: E/AndroidRuntime(597):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
06-17 05:31:55.587: E/AndroidRuntime(597):  ... 4 more
06-17 05:31:56.227: W/IInputConnectionWrapper(597): showStatusIcon on inactive InputConnection
06-17 05:31:58.086: I/Process(597): Sending signal. PID: 597 SIG: 9

1 个答案:

答案 0 :(得分:0)

应用程序正在停止,因为SearchManager未正确实现。

没有SearchManager,没有简单的方法来管理搜索。至少不适合我。而且,另一方面,它是一个功能齐全的搜索引擎,为什么要使用其他工具?