2014-01-21 4 views
12

LoaderManager이 방법 restartLoader() 가지고LoaderManager.restartLoader()는 항상 onCreateLoader()를 호출합니까?

public abstract Loader<D> restartLoader (int id, Bundle args, LoaderCallbacks<D> callback)

새를 시작하거나 매니저 기존 로더 재시작 그것에 콜백을 등록하고,이 (활성/단편은 시작된 경우) 그것을로드하기 시작합니다. 동일한 ID를 가진 로더가 이전에 시작된 경우 새 로더가 작업을 완료하면 자동으로 제거됩니다. 콜백은 이전 로더가 삭제되기 전에 전달됩니다.

the dev guide을 바탕으로, 난 정말, onCreateLoader에 대한 호출은 항상 restartLoader()에서 발생합니다 아이디어를 얻을 :

폐기 ...

로더

를 다시 시작을하여 이전 데이터에서는 restartLoader()를 사용합니다. 예를 들어, SearchView.OnQueryTextListener의이 구현은 사용자 쿼리가 변경 될 때 로더를 다시 시작합니다. 예에서

public boolean onQueryTextChanged(String newText) { 
    // Called when the action bar search text has changed. Update 
    // the search filter, and restart the loader to do a new query 
    // with this filter. 
    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; 
    getLoaderManager().restartLoader(0, null, this); 
    return true; 
} 

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    // NOTE: The Loader is instantiated with the user's query 

    Uri baseUri;  
    if (mCurFilter != null) { 
     baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 
        Uri.encode(mCurFilter)); 
    } else { 
     baseUri = Contacts.CONTENT_URI; 
    } 

    // Now create and return a CursorLoader that will take care of 
    // creating a Cursor for the data being displayed. 
    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" 
      + Contacts.HAS_PHONE_NUMBER + "=1) AND (" 
      + Contacts.DISPLAY_NAME + " != ''))"; 
    return new CursorLoader(getActivity(), baseUri, 
      CONTACTS_SUMMARY_PROJECTION, select, null, 
      Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); 
} 

onCreateLoader는 사용자의 쿼리에 대한 정보가 로더에 전달되는 유일한 장소입니다 : 그것은 새 쿼리를 수행 할 개정 검색 필터를 사용할 수 있도록 로더는 다시 시작해야합니다 (인스턴스화시). 그러나 문서는 '새로운 을 시작하거나 기존 로더를 다시 시작합니다.'이라고 말하면서 저를 버립니다.

답변

24

질문에 대한 간단한 대답은 예입니다. restartLoader()를 호출하면 onCreateLoader()가 다시 호출됩니다.

당신은 병렬로 하나 이상의 로더를 시작할 수 있습니다 예를 들어, (당신이 채우기 위해 두 SimpleCursorAdapters가 있다고 가정) :

getLoaderManager().initLoader(0, null, this); //id = 0 
getLoaderManager().initLoader(1, null, this); //id = 1 

onCreateLoader이 각 ID입니다 (반환되는 로더 로더 관리자에 의해 호출된다 다음) 로더 관리자에 의해 비동기 적으로 내장 :

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) 
{ 
    if (loader.getId() == 0) 
     //cursor was returned from onCreateLoader for id 0 
     //perhaps do swapCursor(cursor) on an adapter using this loader 
    else if (loader.getId() == 1) 
     //cursor was returned from onCreateLoader for id 1 
     //perhaps do swapCursor(cursor) on an adapter using this loader 
} 
:

public Loader<Cursor> onCreateLoader(int id, Bundle args) 
{ 
    if (id == 0) 
     //return a Loader<Cursor> for id 0 
    else if (id == 1) 
     //return a Loader<Cursor> for id 1 
} 

로더 관리자 onLoadFinished에 결과 로더를 전달

당신은 이후에 다시 시작 로더 호출 할 때 :

getLoaderManager().restartLoader(0, null, this); //id = 0 

... 처음이라고 onLoaderReset :

public void onLoaderReset(Loader<Cursor> loader) 
{ 
    if (loader.getId() == 0) 
     //perhaps do swapCursor(null) on an adapter using this loader 
    else if (loader.getId() == 1) 
     //perhaps do swapCursor(null) on an adapter using this loader 
} 

... onCreateLoader에 새로운 호출 다음을. 이 점에서 onCreateLoader는 새로운 로더를 시작하고 기존 로더가 재설정 될 때 사용됩니다.

+0

'onCreateLoader'도 UI 스레드에서 호출된다고 생각합니다 ...! – Maarten

+0

나는 왜 그런 생각을하는지에 관심이 있습니까? ContentProvider/Datasource와 비동기 적으로 상호 작용하는 것은 로더의 핵심입니다.UI를 차단할 수있는 장기 실행 작업은 onCreateLoader에서 실행됩니다. LoaderManager는 백그라운드에서 해당 부분을 실행합니다. – NigelK

+0

예, 그렇습니다. AsyncTaskLoader의 ['loadInBackBackground'] (https://developer.android.com/reference/android/content/AsyncTaskLoader.html) 부분은 반드시 백그라운드 스레드에서 실행되지만 onCreateLoader는 UI 스레드 : [로더의 클라이언트는 일반적으로 프로세스의 기본 스레드 (즉, 활동 콜백 및 기타 작업이 발생하는 스레드)에서 로더에 대한 호출을 수행해야합니다.] (https://developer.android .com/reference/android/content/Loader.html) - 'AsyncTask'를 인스턴스화하는 것과 비슷합니다. 그건 내 추론이었습니다. – Maarten