Какова область применения LoaderManager? - PullRequest
16 голосов
/ 07 сентября 2011

При идентификации загрузчиков в LoaderManager вы используете уникальные идентификаторы. Я спрашиваю, насколько уникальными должны быть эти идентификаторы.

У каждого действия и фрагмента есть свой собственный LoaderManager? Используют ли фрагменты LoaderManager из Действия, к которому они прикреплены? Существует ли только один LoaderManager, которым владеет приложение?

Бонусные баллы, если вы можете сказать мне, как можно изменить используемый LoaderManager. Если я хочу, чтобы каждый фрагмент в моей Деятельности использовал один и тот же LoaderManager (некоторые из них извлекают одни и те же данные, и было бы неплохо делиться загрузчиками), возможно ли это?

Ответы [ 2 ]

8 голосов
/ 30 сентября 2011

В настоящее время я портирую свое приложение на пакет совместимости Android (в основном для CursorLoader и Fragments).В настоящее время я пытаюсь разделить CursorLoader между двумя фрагментами, чтобы сэкономить запрос на мой ContentProvider.Добро пожаловать в мой мир!;)

Простой вариант использования:

- DummyActivity расширяет FragmentActivity / Log.d (Constants.LOGTAG, "DummyActivity.onCreate" + getSupportLoaderManager (). ToString ());

- DataFragment расширяет Fragment, реализует LoaderManager.LoaderCallbacks / Log.d (Constants.LOGTAG, "DataFragment.onCreate" + getLoaderManager (). ToString ());

- ReportFragment расширяет Fragment, реализующий LoaderCanager.Log.d (Constants.LOGTAG, "ReportFragment.onCreate" + getLoaderManager (). ToString ());

DummyActivity создает экземпляр DataFragment, а затем - экземпляр ReportFragment.Выходные данные logcat показывают разные адреса для каждого LoaderManager.Как первый вывод, у каждого фрагмента, похоже, есть свой LoaderManager…

Я продолжу и обновлю, если смогу ответить на ваш (наш;) вопрос.Если вы добились какого-либо прогресса, пожалуйста, поделитесь своими ценными знаниями.

Обновление:

Я предполагаю, что идентификаторы загрузчика связаны только с локальной областью видимости LoaderManagerдля конкретного фрагмента, чтобы позволить нескольким локальным загрузчикам быть связанными с фрагментом (так что вы можете вернуть другой загрузчик в onCreateLoader на основе вызовов id int arg и initLoader).

Пока мне удалось «повторно использовать»"Загрузчик (... или нет):

- Во-первых, я включил отладку LoaderManager с помощью getSupportLoaderManager().enableDebugLogging(true); в методе DummyActivity onCreate.

- Затем я вызвал getActivity().getSupportLoaderManager().initLoader(78, null, this); изonCreate методы как DataFragment, так и ReportFragment.

- DataFragment предоставляет доступ к CursorLoader, созданному методом onCreateLoader, через установщик закрытого члена mCursorLoader.

- ReportFragment onCreateLoaderвозвращает DataFragment CursorLoader (после извлечения фрагмента с помощью findFragmentByTag).

Отфильтрованный (и слегка запутанный) logcatoutput:

      DummyApp  D  DummyActivity.onCreate
      DummyApp  D  DataFragment.newInstance
      DummyApp  D  ReportFragment.newInstance
      DummyApp  D  DataFragment.onCreate
 LoaderManager  V  initLoader in LoaderManager{405a19d0 in SpecificAction{4059ee98}}: args=null
      DummyApp  D  DataFragment.onCreateLoader
 LoaderManager  V    Created new loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
      DummyApp  D  DataFragment.onCreate
      DummyApp  D  DataFragment.onActivityCreated
      DummyApp  D  ReportFragment.onCreate
 LoaderManager  V  initLoader in LoaderManager{405a19d0 in DummyActivity{4059ee98}}: args=null
 LoaderManager  V    Re-using existing loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
      DummyApp  D  SpecificActionReportFragment.onCreate
      DummyApp  D  SpecificActionReportFragment.onActivityCreated
 LoaderManager  V  Starting in LoaderManager{405a19d0 in DummyActivity{4059ee98}}
 LoaderManager  V    Starting: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
 DummyProvider  D  query called
 DummyProvider  D  […]       
 DummyProvider  D  [end of query]
 LoaderManager  V  onLoadComplete: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
 LoaderManager  V    onLoadFinished in CursorLoader{405a22e0 id=78}: CursorWrapperInner{405afb20}
      DummyApp  D  ReportFragment.onLoadFinished
      DummyApp  D  ReportFragment.displayActionReport
      DummyApp  D  DummyActivity.setReportViewsVisibility
      DummyApp  D  ReportFragment.setSaveReportImageViewVisibility

Два фрагмента добавляются из метода DummyActivity onCreate (отличается от описанного варианта использования, но это ничего не меняет в проблеме, над которой мы работаем).К сожалению, загрузчик переназначен на последний фрагмент, вызывающий его (здесь ReportFragment)… и DataFragment.onLoadFinished никогда не вызывается.Как следствие, ReportFragment выглядит хорошо, но DataFragment не обновлен, так как обновление вызывается из onLoadFinished этого класса.

Я предполагаю, что существует основной незарегистрированный вызов, а затем регистрвызовите CursorLoader.

Продолжение следует ...

0 голосов
/ 06 января 2015

Да. Это сработало для меня. У меня есть 3 разных фрагмента в ящике навигации, где одни и те же данные заполнены в разных списках. (Все фрагменты являются частью одного и того же действия).

Мой AsyncTaskLoader:

public class MyTaskLoader extends AsyncTaskLoader<HashMap<String, Integer>> {

public MyTaskLoader(Context context) {
    super(context);
}

@Override
public HashMap<String, Integer> loadInBackground() {
...
return hashMap;
}

...
}

Используйте один и тот же идентификатор загрузчика во всех фрагментах.

Fragment1:

public class Fragment1 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> {
@Override
public void onCreate(Bundle savedInstanceState) {

//initialize adapter

getActivity().getSupportLoaderManager().initLoader(0, null, this);

}

@Override
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) {
    // TODO Auto-generated method stub

    return new MyTaskLoader(getActivity());
}

@Override
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0,
        HashMap<String, Integer> data) {
    // TODO Auto-generated method stub

    listAdapter.setData(data.keySet());

}

@Override
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) {
    // TODO Auto-generated method stub

    listAdapter.setData(null);
}
}

Используйте тот же Id для Fragment2:

public class Fragment2 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> {
@Override
public void onCreate(Bundle savedInstanceState) {

//initialize adapter

getActivity().getSupportLoaderManager().initLoader(0, null, this);

}

@Override
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) {
    // TODO Auto-generated method stub

    return new MyTaskLoader(getActivity());
}

@Override
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0,
        HashMap<String, Integer> data) {
    // TODO Auto-generated method stub

    listAdapter.setData(data.keySet());

}

@Override
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) {
    // TODO Auto-generated method stub

    listAdapter.setData(null);
}
}

Адаптер должен быть инициализирован перед инициализацией загрузчика. Работает до сих пор. Но это правильный путь? Есть ли лучший способ использования общего загрузчика для нескольких фрагментов?

...