6

AsyncTaskLoader でいくつかの問題が発生しています。ローダーを再起動しようとすると両方が発生するため、それらが関連しているかどうかはわかりません。私のアプリケーションには、カスタム CursorAdapter の 3 つのインスタンスがあり、1 つのシングルトン LoaderManager によって管理されるカスタム AsyncTaskLoader の 3 つのインスタンスに支えられています。問題は 2 つの異なるアダプター/ローダーのペアに関連していますが、使用されるコードはいずれの場合も同じです。

getLoaderManager().restartLoader(loaderId, bundle, loaderManager);

問題 1: restartLoader() を呼び出すと、LoaderManager は onCreateLoader への呼び出しを登録しますが、onLoaderReset() への呼び出しは登録しません。ローダーは deliveryResult() を取得しますが、onLoadFinished() は呼び出されません。ローダーには、'reset' または 'started' フラグが設定されていません (以下のコードを参照)。

問題 2: restartLoader() を呼び出すと、LoaderManager が onLoaderReset() への呼び出しを登録します。ローダーは onReset() に到達しますが、それ以上到達しません。Cursor は null に設定されていますが、新しい Cursor はロードされていません。

問題の可能性はありますか?ローダーとローダー マネージャーのコードの一部を次に示します。

CustomCursorLoader.java

@Override
protected void onStartLoading() {
    Log.v(TAG, "Starting Loader");
    if (lastCursor != null) {
        deliverResult(lastCursor);
    }
    if (takeContentChanged() || lastCursor == null) {
        forceLoad();
    }
}

@Override
public void deliverResult(Cursor cursor) {
    Log.v(TAG, "Delivering result");
    if (isReset()) {
        Log.v(TAG, "reset");
        if (cursor != null) {
            cursor.close();
        }
        return;
    }
    Cursor oldCursor = lastCursor;
    lastCursor = cursor;
    if (isStarted()) {
        Log.v(TAG, "started");
        super.deliverResult(cursor);
    }
    if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
        oldCursor.close();
    }
}

@Override
protected void onReset() {
    Log.v(TAG, "Reset");
    super.onReset();
    onStopLoading();
    if (lastCursor != null && !lastCursor.isClosed()) {
        lastCursor.close();
    }
    lastCursor = null;
}

CustomCursorLoaderManager.java:

@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
    return new CustomCursorLoader();
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    cursorAdapter.changeCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    cursorAdapter.changeCursor(null);
}
4

2 に答える 2

1

「LoaderManager」と呼んでいるものは、実際にはLoaderManager.LoaderCallbacks<D>インターフェースの実装です。別の名前を使用することをお勧めします。これは紛らわしいです。なぜシングルトンなのですか?通常は、アクティビティまたはフラグメントに関連付けられています。おそらく、インターフェイスを実装するアクティビティ/フラグメントだけです。ローダー (アクティビティ/フラグメント) はどこで作成していますか? また、必ずLoaderManager.initLoader()から呼び出すようにしてくださいonCreate()/onActivityCreated()。そうしないと、ローダーが適切に起動されない可能性があります。

于 2011-08-23T02:45:59.093 に答える
0

カーソルを作成してデータベースをポイントする場合、単に null に設定することはできません。カーソルを明示的に閉じる必要があります。そうしないと、タイムアウトになるまでデータベースがロックされます。

Android ライフサイクルと既存のコールバックを利用して、この修正を実装することをお勧めします。

お役に立てれば!

于 2011-08-22T20:47:31.873 に答える