2012-06-08 11 views
6

onLoadFinishedコールバック(LoaderManager.LoaderCallbacks)でカーソルが返されました。このカーソルで後処理を行う場合があります。だから、私はAsyncTaskこのカーソルを使用して発砲しています。しかし、私はこの例外に断続的にクラッシュを取得しています:バックグラウンドスレッドがで終了する前に(UIスレッドでローダーによって管理されている)、カーソルがクローズされているので、AsyncTaskでLoaderManagerから返されたカーソルを使用する

android.database.StaleDataException: Attempted to access a cursor after it has been closed. 

私の疑惑は、これが起こっているということですこれは管理されたカーソルであるためです。

private class LoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { 
    @Override 
    public void onCreateLoader(int d, Bundle args) { 
     return new CursorLoader(context, uri, projection, selection, selectionArgs, sortOrder); 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
     processCursor(cursor)  
    } 
} 

private void processCursor(final Cursor cursor) { 
    new AsyncTask<Void, Void, Result> { 
     @Override 
     Result doInBackground(Void... params) { 
      while(cursor.isAfterLast() == false) { 
       // doing some costly things with cursor 
      } 
     } 
    }.execute(); 
} 

それはどちらかが可能である、

  1. は、どういうわけか、UIスレッドから閉鎖されてからそれを防ぐために、カーソルをフラグ:ここではいくつかの言い換えコードです。

  2. カーソルがまだ使用中であることをマネージャに通知します。

  3. 複製されたインスタンスがマネージャによって閉じられないように複製します。

  4. もう1つ、さらに優れたソリューションですか?

この後処理をUIスレッドで行うことは、非常にコストがかかる可能性があるため、絶対に選択肢ではありません。

+1

'CursorLoader'をスキップして、初期クエリ+高価な処理を' AsyncTask'で行うことができます。 – Luksprog

+0

このカーソルを他のものに使用していますか? – njzk2

答えて

2

カーソルをUIスレッドから閉じないようにカーソルを何らかの形でフラグを立てることはできますか?

いいえ(よく、内部APIを書き換えないでください)。

カーソルがまだ使用中であることをマネージャに通知することはできますか?

上記と同じ回答です。

複製されたインスタンスがマネージャによって閉じられないように複製できますか?

これはちょっと混乱しています...そして、LoaderManagerがクローンを終了する前にカーソルを閉じる機会がまだあります。

もっと良い解決策はありますか?

はい。 LoaderManagerに渡したものを再利用しようとするのではなく、新しいカーソルを照会してください。

+0

あなたはもっと具体的になることができますか?あなたの答えを私の理解から、私はまだ同じ問題につながる、新しいカーソルを後処理する必要があります...? –

+0

あなたは何をしようとしているのですか?あなたの "後処理"が 'LoaderManager'ライフサイクルで結ばれているのはなぜですか?別々に扱ってみませんか?そんなにクリーンなのは... –

0

男、私はまったく同じ問題に直面しています。方法は、アクティビティのonDestroyメソッドでasynctaskをキャンセルすることです。

private YourAsyncTask asyncTask 

@Override 
protected void onDestroy(){ 
    super.onDestroy(); 
    asyncTask.cancel(true); 
} 
関連する問題