0

Loaderによって編集されているデータベースを取得するために s を使用しているアプリケーションがありますIntentService。正常に動作している実装Loaderを通じてからデータを受け取ります。LoaderCallbacks

ContentResolver#notifyChange(Uri, ContentObserver)リロードのトリガーにも使用しています。ただし、これはCursor#setNotificationUri(Uri)事前に電話した場合にのみ機能します。

どのドキュメントにも後者の方法への参照が見つかりません。実際、これがクラッシュを引き起こしている可能性があるようです: も参照してください。

ContentProvider の SimpleCursorAdapter で IllegalStateException "既に閉じられているオブジェクトを再度開こうとしています"

ただし、この呼び出しがないと、通知後CursorLoaderCallbacks#onLoadFinished(Loader<Cursor>, Cursor)はなく、初期ロード後にのみヒットします。またOnLoadCompleteListener、まったく同じことを行う必要がありますか?

ContentProviderクエリ方法:

class MyContentProvider extends ContentProvider {
//...

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        Cursor query = db.query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder);
        query.setNotificationUri(getContext().getContentResolver(), uri);
        return query;
    }

//...
}

典型的なLoaderCallbacks:

LoaderCallbacks<Cursor> mCallbacks = new LoaderCallbacks<Cursor>() {

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mArticleAdapter.swapCursor(null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        if(cursor.isClosed()) {
            Log.d(TAG, "CURSOR RETURNED CLOSED");
            Activity activity = getActivity();
            if(activity!=null) {
                activity.getLoaderManager().restartLoader(mFragmentId, null, mCallbacks);
            }
            return;
        }
        mArticleAdapter.swapCursor(cursor);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        triggerArticleFeed();
        CursorLoader cursorLoader = null;

        if(id == mFragmentId) {
            cursorLoader = new CursorLoader(getActivity(),
                                            MyContentProvider.ARTICLES_URI,
                                            null,
                                            ArticlesContentHelper.ARTICLES_WHERE,
                                            ArticlesContentHelper.ARTICLES_WHEREARGS,
                                            null);
        }
        return(cursorLoader);
    }
};
4

1 に答える 1

1

両方のリスナーを実装することは非常に悪い考えです。

02-19 17:46:25.139: E/AndroidRuntime(24886): FATAL EXCEPTION: main
02-19 17:46:25.139: E/AndroidRuntime(24886): java.lang.IllegalStateException: There is already a listener registered
02-19 17:46:25.139: E/AndroidRuntime(24886):    at android.content.Loader.registerListener(Loader.java:152)
02-19 17:46:25.139: E/AndroidRuntime(24886):    at android.app.LoaderManagerImpl$LoaderInfo.start(LoaderManager.java:273)
02-19 17:46:25.139: E/AndroidRuntime(24886):    at android.app.LoaderManagerImpl.installLoader(LoaderManager.java:523)
02-19 17:46:25.139: E/AndroidRuntime(24886):    at android.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:510)
02-19 17:46:25.139: E/AndroidRuntime(24886):    at android.app.LoaderManagerImpl.initLoader(LoaderManager.java:563)

したがって、実際には、この質問に対する答えは次のとおりです。

両方のリスナーを実装しないようにする必要があります。

于 2013-02-19T17:50:09.923 に答える