2012-06-08 2 views
6

onLoadFinished 콜백 (LoaderManager.LoaderCallbacks)에서 커서가 반환되었으며이 커서에서 약간의 (값 비싼) 후가공 작업을 수행하려고합니다. 그래서이 커서를 사용하는 AsyncTask을 발사하고 있습니다. 그러나, 나는이 예외에 간헐적 인 충돌을 받고 있어요 :AsyncTask에서 LoaderManager에서 반환 된 커서 사용

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

내 의심이가 커서 (UI 스레드에서 로더에 의해 관리되는) 때문에 일어나는 백그라운드 스레드가 완료되기 전에 폐쇄되고있는 것입니다 이것은 관리 된 커서이기 때문에.

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. 또 다른, 더 나은 솔루션입니까?

그러나 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); 
} 
관련 문제