Глобальный загрузчик (LoaderManager) для повторного использования в нескольких действиях / фрагментах

То, что я хотел бы достичь:

У меня есть два разных фрагмента. Я бы хотел, чтобы они оба отображали одни и те же данные в двух формах (в списке и на карте). Я бы хотел, чтобы они AsyncTaskLoader один загрузчик (в частности, AsyncTaskLoader ). Все работает нормально, но Loader не используется повторно. Создается другая, и данные загружаются дважды.

Что я делаю:

В Fragment s используется LoaderManager lm = getActivity().getSupportLoaderManager(); В обоих из них я реализую LoaderCallbacks<ArrayList<Item>> и необходимые методы. В обоих случаях я использую lm.initLoader(0, args, this); ,

Но когда я lm.toString() кажется, что это два разных загрузчика. И данные загружаются дважды.

Как повторно подключиться к одному загрузчику из другого Activity / Fragment, чем тот, в котором он был запущен?

Это должно быть возможным, поскольку контекст подключен к загрузчику в любом случае на каждом onCreate() , например, при изменении конфигурации.

Solutions Collecting From Web of "Глобальный загрузчик (LoaderManager) для повторного использования в нескольких действиях / фрагментах"

Как повторно подключиться к одному загрузчику из другого Activity / Fragment, чем тот, в котором он был запущен?

Вы не должны повторно использовать Loader s, которым управляет экземпляр LoaderManager через несколько Activity s и Fragment s.

LoaderManager запустит / остановит эти Loader s относительно жизненного цикла Activity / Fragment , поэтому нет способа гарантировать, что эти Loader s будут существовать, когда вы находитесь в другом Activity .

Из документации:

LoaderManager.LoaderCallbacks – это интерфейс обратного вызова, который позволяет клиенту взаимодействовать с LoaderManager.

Ожидается, что загрузчики, в частности CursorLoader, сохранят свои данные после остановки. Это позволяет приложениям сохранять свои данные во всех операциях или методах onStop () и onStart (), поэтому, когда пользователи возвращаются в приложение, им не нужно ждать перезагрузки данных. Вы используете методы LoaderManager.LoaderCallbacks, когда знаете, когда создавать новый загрузчик, и сообщать приложению, когда пришло время прекратить использование данных загрузчика.

Другими словами, часто бывает, что ваш Loader s будет специфичен для какой-либо Activity (или Fragment). Когда у вас есть Activity реализующий интерфейс LoaderManager.LoaderCallbacks , вашей Activity присваивается тип LoaderManager.LoaderCallbacks . Каждый раз, когда вы вызываете initLoader(int ID, Bundle args, LoaderCallbacks<D> callback) , LoaderManager создает или повторно использует Loader , специфичный для некоторого экземпляра интерфейса LoaderManager.LoaderCallbacks (который в этом случае является экземпляром вашей активности ). Это по существу связывает вашу активность с загрузчиком, и ее методы обратного вызова будут вызваны в качестве изменений состояния загрузчика.

При этом, если вы не найдете способ, чтобы ваши две отдельные действия использовали одни и те же методы обратного вызова, я сомневаюсь, что есть чистый способ сделать это (т. Е. Иметь активность и фрагмент совместно использовать одни и те же обратные вызовы, как будто это было бы сложно , Если не невозможно). Я бы не стал беспокоиться об этом слишком много. Во всем примере кода, который я когда-либо видел, я никогда не видел, чтобы две операции и / или фрагменты использовали одни и те же методы обратного вызова. Кроме того, учитывая, что Activity s и Fragment s должны быть предназначены для повторного использования, разделение Loader s таким образом просто не похоже на то, что было бы поощрено.

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

Мой 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); } } 

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

Я не совсем уверен, что вы пытаетесь архивировать после обсуждения. Но есть метод application.registerActivityLifecycleCallbacks() , который принимает слушателей жизненного цикла глобальной активности (например, onActivityCreated() ).

Я думаю, что у вас будет желаемое поведение, если вы используете один и тот же идентификатор загрузчика для разных фрагментов и действий. Убедитесь, что идентификатор загрузчика уникален для данных для загрузки. PhotosLoader и VideoLoader не должны иметь одинаковый идентификатор, например.