2011-08-22 2 views
6

AsyncTaskLoader에 몇 가지 문제가 있습니다. 로더를 재시작하려고 할 때 발생하는 두 가지 문제가 있습니다. 내 응용 프로그램에는 하나의 싱글 톤 LoaderManager에 의해 관리되는 사용자 정의 AsyncTaskLoader의 3 인스턴스가 지원하는 사용자 정의 CursorAdapter 인스턴스가 3 개 있습니다. 문제는 두 differenct 어댑터/로더 쌍과 관련되지만 사용되는 코드는 각각의 경우에서 동일하다 :커스텀 AsyncTaskLoader 콜백 문제들

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

문제 1 : I는 restartLoader을 (통화) 및 LoaderManager는 하나를 onCreateLoader 호출 등록 아니지만 onLoaderReset(). 로더가 deliverResult()에 도착하지만 onLoadFinished()가 호출되지 않습니다. 로더에는 '재설정'또는 '시작됨'플래그가 설정되어 있지 않습니다 (아래 코드 참조).

문제 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); 
} 

답변

1

'LoaderManager'는 실제로는 LoaderManager.LoaderCallbacks<D> 인터페이스의 구현입니다. 다른 이름을 사용하고 싶을 수 있습니다.이 이름은 혼란 스럽습니다. 왜 싱글 톤입니까? 일반적으로 인터페이스를 구현하는 액티비티 또는 프래그먼트에만 연결됩니다. 로더 (액티비티/프래그먼트)는 어디에서 생성합니까? 또한 LoaderManager.initLoader()onCreate()/onActivityCreated()에서 호출해야합니다. 그렇지 않으면 로더가 제대로 시작되지 않을 수 있습니다.

+0

1. 그 이름이 분명하지 않은 것을 알고 있습니다. 미안합니다. 2. 더 이상 싱글 톤이 아닙니다. 해당 부분에서 작업 중입니다. 3. 주요 문제는 동일한 로더를 사용하여 동일한 커서를 사용할 수있게하려는 것입니다. 서로 다른 단편을 묶은 단락 – Pikaling

+0

왜 커서를 공유 하시겠습니까? 로더는 액티비티/파편에 의해 관리되므로 다른 액티비티가 완료되면 로더가 닫힐 수 있습니다. 동일한 로더 _class_를 사용하여 다른 액티비티/프래그먼트에서 인스턴스화하도록 할 수 있습니다. –

+0

도움 주셔서 감사합니다. 나는 일하며 모든 코드를 수정했다. 때때로 나는 OOP를 싫어한다 ... – Pikaling

0

당신이 커서를 생성하고 데이터베이스에 그것을 지적하면 null로 설정할 수 없습니다. 명시 적으로 커서를 닫거나 시간이 초과 될 때까지 데이터베이스를 잠급니다.

이 수정 프로그램을 적용하려면 Android 라이프 사이클과 기존 콜백을 활용하는 것이 좋습니다.

희망이 도움이됩니다.

+0

좋은 캐치 - changeCursor()가 아님 swapCursor() - 이제 변경했습니다. – Pikaling

+0

에 여전히 동일한 문제가 있습니까? – Codeman

+0

아니요. 나는 그것을 고치려고 노력했고 더 심하게 만들었습니다! 항상 ... – Pikaling

관련 문제