2012-05-09 2 views
1

Всегда ли необходимо initLoader из onCreate in Fragment? Что делать, если критические аргументы для загрузчика зависят от результатов другого загрузчика?Delaying Loaders

У вас есть 2 погрузчика: LoaderA и LoaderB. LoaderB требует результата от LoaderA для запуска. Оба LoaderA и LoaderB инициализируются в onCreate фрагмента, но LoaderB не имеет аргументов, чтобы он умышленно терпел неудачу. Как только LoaderA заканчивается, LoaderB перезапускается с новыми аргументами, чтобы он мог выполнить желаемый запрос.

инициализации загрузчика в фрагменте:

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    getLoaderManager().initLoader(LOADER_A, new Bundle(), this); 
    getLoaderManager().initLoader(LOADER_B, null, mLoaderBCallback); 
} 

вызова спины для LOADER_A в фрагменте:

@Override 
public Loader<MyResultObject> onCreateLoader(int id, Bundle args) { 
    return new LoaderA(getActivity(), args); 
} 

@Override 
public void onLoadFinished(Loader<MyResultObject> loader, final MyResultObject result) { 
    if (result != null) { 
     Bundle args = new Bundle(); 
     args.putInt("id", result.getId()); 

     getLoaderManager().restartLoader(LOADER_B, args, mLoaderBCallback); 
    } 
} 

Определение mLoaderBCallback в фрагменте:

private LoaderBCallback mLoaderBCallback = new LoaderBCallback(); 

(Реализация LoaderBCallback не является важно, его просто стандартный интерфейс LoaderCallbacks, который . Атес Экземпляр LoaderB и ручки, когда погрузчик закончена)

класс LoaderB (пожалуйста, простите любые потенциальные ошибки компилятора с этим определением класса, его просто пример):

public class LoaderB<List<AnotherResultObject>> extends AsyncTaskLoader<List<AnotherResultObject>> { 
    private Bundle mArgs; 

    public LoaderB(Context context, Bundle args) { 
     super(context); 
     mArgs = args; 
    } 

    @Override 
    public List<AnotherResultObject> loadInBackground() { 
     if (mArgs == null) { 
      // bail out, no arguments. 
      return null; 
     } 


     // do network request with mArgs here 
     return MyStaticClass.performAwesomeNetworkRequest(mArgs); 
    } 

    // boiler plate AsyncTaskLoader stuff here 
    ...... 

} 

есть лучший способ ? Можем ли мы обойтись без initLoader для LoaderB?

Редактировать: У меня создается впечатление, что загрузчики ВСЕГДА должны быть инициализированы в onCreate, чтобы они могли обрабатывать изменения конфигурации. Это может быть справедливо ТОЛЬКО для загрузчиков в действиях. Создаются ли загрузчики, созданные во Фрагментах, независимо от того, где они инициализируются?

ответ

1

Вы можете запустить загрузчик в любом месте вашего кода.

В вашем случае вы должны заменить restartLoader на onLoadFinished с помощью initLoader. Просто удалите initLoader из вашего onActivityCreated для LOADER_B

Кроме того, вы должны проверить идентификатор загрузчика в onLoadFinished, чтобы вы знали, какой загрузчик закончен.

редактирования: вы используете отдельный приемник для LOADER_B обратного вызова, так мой ID точки проверки своего рода получает побежденной там .. но в любом случае .. Вы можете объединить их в один, если вы хотите

@Override 
public void onLoadFinished(Loader<MyResultObject> loader, final MyResultObject result) { 
    switch (loader.getId()) 
    { 
     case LOADER_A: 
     if (result != null) { 
      Bundle args = new Bundle(); 
      args.putInt("id", result.getId()); 
      // i put "this" as the callback listener. you can use your custom one here if you want 
      getLoaderManager().initLoader(LOADER_B, args, this); 
     } 
     break; 
     case LOADER_B: 
     //do whatever 
     break; 
} 
+0

Любая идея если загрузчик все еще переживет события жизненного цикла (например, изменение ориентации), если вы не начнете их где-то важными? – NPike

+0

Он должен. Результат загрузчика сохраняется после изменения ориентации. – dymmeh

Смежные вопросы