Объекты связи между несколькими фрагментами в ViewPager

У меня есть 5 фрагментов в ViewPager, используемых для заполнения бизнес-объекта несколькими полями шаг за шагом, на каждом шаге будут установлены некоторые из этих полей. Я прочитал много статей о связи между фрагментами, но я не чувствую себя комфортно, как другие предпочитают, поэтому, подумав о том, как я должен это сделать в моем случае, я, наконец, начинаю думать о том, чтобы использовать одномодовый модельный объект, который все фрагменты могут легко получить к его полям и заполнить их конкретными шагами.

Поскольку я новичок в android, я хочу услышать от экспертов об использовании singleton вместо передачи данных между фрагментами, такими как реализованный интерфейс (кажется, это так сложно и сложно поддерживать). Любые советы будут полезны.

Ответы

Ответ 1

Хотя одноэлементный подход кажется простым в реализации и понимает, что это не лучший способ добиться того, что вам нужно. Одна из причин заключается в том, что ваш объект модели или, как вы называете его бизнес-объектом, живет вне контекста активности, который может затруднить поиск ошибок. Например. в случае, когда более одного экземпляра вашего класса активности создается системой, и оба сохраняют ссылку на ваш синглтон. Посмотрите, как вы теряете отслеживание своих объектов?

Что бы я сделал,

  • Сделайте объект модели для Parcelable, вы будете ненавидеть его в начале, но как только вы его используете, он станет вашим модель лучший друг
  • Так как ваша модель Parcelable теперь вы можете легко передать ее между фрагментами, действиями и даже сохранить их в общих настройках. Важно отметить, что когда вы передаете Parcelable между фрагментом или активностью, это похоже на пропуск по значению, т.е. каждый раз, когда создается новый экземпляр.
  • Задайте аргумент фрагмента или он уже создан, затем получите аргументы и добавьте вашу модель. вот пример: если фрагмент еще не активен:

    Bundle args = new Bundle(); args.putParcable("businessObject", yourBusinessObjectThatIsParcable); yourFragment.setArguments(args);

    В противном случае:    yourFragment.getArguments().putParcelable("businessObject", yourBusinessObjectThatIsParcable);

  • В вашем фрагменте, возможно, в методе onCreateView получите свой объект модели, подобный этому MyParcableObject mpo = (MyParcableObject)getArguments().getParcelable("businessObject"), и используйте его, чтобы установить любые нужные вам данные.

  • Когда вы закончите редактировать свой объект при нажатии кнопки или в методе onPause, обновите аргументы фрагмента таким же образом getArguments().putParcelable("businessObject", mpo);

  • на последней странице или последнем фрагменте вы можете передать свой объект своей деятельности, здесь, как это сделать

Несмотря на то, что он выглядит громоздким, но это практика, вам нужно привыкнуть к разработчику Android. Вы получаете намного больше контроля, когда ваша модель реализует Parcelable.

Другой способ сделать то, что вам нужно, - это Delegation Pattern, но в основном используется для обратных вызовов, даже если вы также можете передавать объекты.

Ответ 2

Я бы не рекомендовал глобальный синглтон. Существуют две основные причины:

  • По определению, singleton ограничивает ваше приложение одним экземпляром основного бизнес-объекта. Если вы (или дизайнер, или босс босс босс) когда-либо решили иметь несколько из этих ViewPagers за один раз, вам все равно придется менять свою архитектуру.
  • "Мысль Android" должна ожидать, что ваш пользователь может разместить ваше приложение в фоновом режиме и использовать другие приложения, прежде чем вернуться в ваше приложение. Если система решит убить ваше приложение в фоновом режиме, ваш объект памяти singleton будет уничтожен, и ваш пользователь потеряет все свои успехи. Правильный способ сохранения состояния Android - это сохранить состояние в Activity или Fragment, соответственно сохранить его в onSaveInstanceState() и восстановить его в onCreate().

Все фрагменты в ViewPager могут получить ссылку на родительскую активность через вызов getActivity(). Или если ваш ViewPager находится внутри фрагмента, тогда все фрагменты могут обращаться к родительскому фрагменту через вызов getParentFragment(). Затем вы можете передать результат в соответствующий класс (или, еще лучше, интерфейс) и сделать вызовы методов для передачи данных взад и вперед. Отслеживайте свои бизнес-данные в родительской активности/фрагменте. Таким образом, вам не нужен глобальный синглтон

Например,

public class MyParentFragment extends Fragment {

  private String mPageOneData;
  private int mPageTwoData;
  private List<Date> mPageThreeData;

  public void setPageOneData(String data) {
    mPageOneData = data;
  }

  ...
}

public class PageOneFragment extends Fragment {

  private void sendDataToParent(String data) {
    Fragment f = getParentFragment();
    if (f != null && f instanceof MyParentFragment) {
      MyParentFragment parent = (MyParentFragment) f;
      f.setPageOneData(data);
    }
  }

}

Ответ 3

  • вы можете сохранить свои данные в событии onSaveInstanceState() в случае, если ваш процесс перейдет в фоновый режим. вы можете восстановить свои данные в событии onCreate(), используя Bundle и getExtras().

  • вы можете сохранить свои данные в классе приложения, и данные все равно будут присутствовать, если ваш процесс перейдет в фоновый режим.

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

Ответ 4

Вы проверили EventBus?

Я не уверен, что это лучший подход, особенно когда ваш вопрос слишком широк, однако это будет здорово всего с 5 фрагментами.

Надеюсь, что это поможет

Ответ 5

Я полагаю, что в вашем MainActivity есть ViewPager, а FragmentOne будет одним из фрагментов внутри пейджера представления. Здесь MainActivity связывается с FragmentOne, чтобы обновить адаптер. Надежда понятна.

В свой MainActivity добавьте этот интерфейс:

public interface Updateable {
    public void update();
}

Внедрите этот интерфейс в фрагмент, который необходимо обновить, и напишите код, чтобы уведомить адаптер внутри метода update:

public class FragmentOne extends Fragment implements MainActivity.Updateable {
    ...
    @Override
    public void update() {
        // YOUR CODE TO UPDATE HERE, FOR EXAMPLE, HERE I'M UPDATING THE ADAPTER
        if ( adapter != null ) {
            adapter.notifyDataSetChanged();
        } else {
            Log.d("LOG_TAG", "null");
        }
    }
    ...
}

Вызвать метод update из MainActivity, когда сначала загружается фрагмент. Вы можете сделать это, переопределяя метод getItemPosition в PagerAdapter, например:

@Override
public int getItemPosition(Object object) {    
    if ( object != null && object instanceof FragmentOne ) {
        FragmentOne f = (FragmentOne) object;

        f.update();
    }
    return super.getItemPosition(object);
}

Наконец, вы должны вызвать notifyDataSetChanged() вашего адаптера viewPager. Это заставит адаптер вашего viewpager вызвать метод getItemPosition.

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        int previousState;
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {

            if (previousState == ViewPager.SCROLL_STATE_SETTLING && state == ViewPager.SCROLL_STATE_IDLE) {

                if ( viewPagerAdapter.getItem(viewpager.getCurrentItem()) instanceof Pictures ) {
                    Log.d("LOG_TAG", "New Position=" + viewpager.getCurrentItem());

                    viewPagerAdapter.notifyDataSetChanged();
                }

            }
            previousState = state;
        }
    });

Ответ 6

Прежде чем выбрать какой-либо вариант, имейте в виду, что пользователь может перемещаться или открывать любые другие приложения, чтобы вы потеряли свои данные.

Вы можете использовать onSaveInstanceState, но это будет как-то сложно поддерживать (как вы сказали, вы новичок в андроиде). Вы можете использовать один синглтон, используя

  • База данных. Используйте, когда вы хотите хранить несколько записей, но вам нужно создать базу данных getter/setter или использовать любой ORM, такой как RushOrm и т.д.
  • SharefPreference (желательно) - Если вы хотите использовать одиночные значения.

В обоих случаях вы создадите одноэлементный объект и получите доступ к его свойствам в своих фрагментах.

Ответ 7

сделайте ваши объекты разумными, а затем передайте их другим фрагментам с помощью пакета. i.e bundle.putParcelable(obj) parcelable очень эффективен и быстр.

он должен мотивировать вас

http://www.developerphil.com/parcelable-vs-serializable/