2013-06-05 4 views
3

업로드 할 일련의 파일이 있습니다. 그것들은 컨텐츠 제공자의 항목으로 저장됩니다. 각 항목에는 업로드 된 비율도 포함됩니다.Android - 어댑터에 정의 된 ContentObserver 등록 해제

하나의 활동은 업로드 목록을 표시하며, 각 파일은 업로드 진행률을 표시하는 ProgressBar가있는 항목입니다.

진행률 표시 줄을 업데이트하는 방법은 ContentObserver를 통해 이루어집니다. CursorAdaptor 내에서 각 항목에 대한 ContentObserver를 정의하고 해당 뷰의 태그로 저장합니다.

지금 내 문제는 그런 ContentObservers를 언제 등록 해제해야할지 모르겠다.

for (int i = 0; i < mListView.getChildCount(); i++) { 
     final View v = mListView.getChildAt(i); 
     final ContentObserver obs = (ContentObserver) v.getTag(); 
     if (obs != null) { 
      getContentResolver().unregisterContentObserver(obs); 
     } 
    } 

이것은 정말, 정말 끔찍한 : 내가 찾은 유일한 방법은 포함 활동의 onDestroy()했다. 어댑터와 상위 활동 간의 종속성을 도입합니다. 반면 등록되지 않은 ContentObservers는 활동이 파괴되어 메모리 누수가 발생하는 것을 막을 수 있습니다.

더 좋은 방법이 있습니까?

+2

적어도 onDestroy()가 호출 될 때나 시스템이 죽일 것으로 예상 할 수는 없으므로 등록 해제 루프를 적어도 onPause()로 이동해야합니다 (결과적으로 onResume()에 등록해야합니다) 앱을 호출하지 않고도 – ozbek

+1

@shoe_rat, 이것은 사실이 아닙니다. ContentObserver를 등록한 라이프 사이클 방법에 달려 있습니다. onCreate에서 등록 호출을 수행하는 동안 onPause에서 등록을 취소하면 해당 활동으로 여러 번 돌아가거나 (또는 ​​추가 점검이 필요함) 폭탄이 터집니다. 또한 시스템이 앱을 죽인 경우에 대해 말한 것은 등록 된 ContentObserver가 시스템에서 사용자를 죽이면 시스템에서 등록이 취소되므로 사실이 아닙니다 (물론, 사용하지 않으면 리소스가 삭제되는 동안 먹을 수도 있습니다). 항상). – Pepster

+1

상태를 뷰, 뷰에 연결하지 마십시오. 모든 데이터를 담고있는 객체를받는 옵서버 하나를 등록하고 그 데이터를 어댑터에 업데이트하고 어댑터의'notifyDataSetInvalidated()'를 호출하십시오. –

답변

0

콘텐츠 공급 업체가있는 경우 대신 CursorLoader를 사용할 수 있습니다.

https://developer.android.com/training/load-data-background/setup-loader.html

public class PhotoThumbnailFragment extends FragmentActivity implements 
     LoaderManager.LoaderCallbacks<Cursor> { 
... 
} 

/* 
* Callback that's invoked when the system has initialized the Loader and 
* is ready to start the query. This usually happens when initLoader() is 
* called. The loaderID argument contains the ID value passed to the 
* initLoader() call. 
*/ 
@Override 
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) 
{ 
    /* 
    * Takes action based on the ID of the Loader that's being created 
    */ 
    switch (loaderID) { 
     case URL_LOADER: 
      // Returns a new CursorLoader 
      return new CursorLoader(
         getActivity(), // Parent activity context 
         mDataUrl,  // Table to query 
         mProjection,  // Projection to return 
         null,   // No selection clause 
         null,   // No selection arguments 
         null    // Default sort order 
     ); 
     default: 
      // An invalid id was passed in 
      return null; 
    } 
} 

당신은 커서 로더를 정의하고 콜백을 구현하고 콘텐츠 관찰자에 대한 필요가 없습니다. 훨씬 잘 작동합니다.