Подтвердить что ты не робот

Лучшая практика для обновления аргументов фрагмента?

Я знаю о "newInstance" -Pattern (Лучшая практика для создания нового фрагмента Android). Но как я могу обновить эти аргументы фрагмента, например, если другой фрагмент изменяет данные?

Я знаю о методах обратного вызова между Fragments/Activitys, но эти обратные вызовы не будут обновлять аргументы?!

Например: при создании фрагмента я передаю ему URI с пакетом. Затем другой фрагмент изменяет этот URI посредством обратного вызова метода changeUri (Uri uri) для первого фрагмента. Если после этого фрагмент будет восстановлен (например, из-за поворота экрана), он будет использовать первый URI из набора аргументов вместо более позднего обновленного uri, правильно?

Какова наилучшая практика для решения этой проблемы? Должен ли я вручную хранить его в файле savedInstanceState и при использовании решить, использовать ли instanceState или arguments-bundle?

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

private Uri arg1;

public static Fragment newInstance(Uri arg1) {
  create bundle
  create fragment instance
  set bundle to fragment
  return fragment
}

private void onCreate(Bundle savedInstance) {
  if(savedInstance != null) {
    arg1 = savedInstance.uri
  }
}

private Uri getUri() {
  if(arg1 == null) {
    arg1 = getArguments.uri
  }
  if(arg1 == null) {
    arg1 = defaultValue
  }
}

Итак, у меня есть простой способ доступа к моему аргументу. И не нужно использовать if-else-hassle, каждый раз, когда мне нужен этот аргумент.

Что вы думаете об этом?

4b9b3361

Ответ 1

Вы не можете изменить аргументы, когда его набор и Fragment добавлены в Activity, я использовал подобный подход, который вы определили сами. Я сначала проверил Bundle, переданный в onCreate(), если его не null я использую его, но если его значение null, то я использую аргументы. И я сохраняю все новейшие данные в onSaveInstanceState(). Для более подробной информации: Возможно ли передать аргументы фрагменту после его добавления в действие?

Ответ 2

Вы сохраняете состояние так же, как и в разделе "Действия в фрагменте" onSaveInstanceState. Если вы обновили URI с последнего onCreate(), вы сохранили бы обновленный URI в Bundle и получили бы это обратно в onCreate(). Сохранение состояния - это именно то, для чего это предназначено, и, изменив URI, все, что вы сделали, изменило состояние.

Ответ 3

Я просто изменяю значение в пакете Пример:

synchronized (fragment.getArguments()) {
        fragment.getArguments().putInt(KEY, new Value);
    }

И обновить содержимое с помощью нового аргумента

Ответ 4

Best practice for updating arguments of a fragment. Почему нам нужно добавить аргумент методом NewInstance() и почему это лучший метод для фрагмента?

Фрагмент можно рассматривать как модульный раздел активности. Это означает, что когда мы создаем фрагмент, нам нужно сделать его модульным и независимым.

Предположим, вам нужен фрагмент, которому нужен аргумент для работы. Мы также можем записать его

MyFragmentClass mFrag = new MyFragmentClass();
Bundle bundle = new Bundle();
bundle.putString("key", value);
mFrag.setArguments(bundle);

Он также отлично работает, и вы можете получить аргумент onCreate. Вот в чем разница, что вы также можете сделать экземпляр фрагмента без аргумента и добавить его в диспетчер фрагментов, но ваш фрагмент нуждается в аргументе для работы. Добавление метода newInstance в фрагменте заставляет разработчика добавлять аргумент при создании. Вот почему говорят о лучших практиках.

В вашей проблеме вы можете использовать setRetainInstance(boolean retain), которые предотвращают уничтожение вашего фрагмента при уничтожении активности.

Ответ 5

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

Например, если у вас есть много фрагментов в общем шаблоне пэга tab/view и управляет ими с помощью FragmentStatePagerAdapter, может быть возможность для вашей активности или других фрагментов ссылаться на экземпляр фрагмента, который больше не существует, заставляя нулевой указатель исключение.

Способ, которым вы можете обойти это, если вы не хотите писать обратные вызовы, заключается в использовании Intents и BroadcastReceivers (которые могут быть немного переполнены и сложны в управлении, но если все сделано правильно, можно сэкономить много головной боли в мой опыт) отправлять и получать трансляции в родительскую активность и обратно.

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

Ответ 6

Если вы хотите повторно использовать фрагмент, но вам нужно обновить аргументы, вам нужно использовать fragment.getArguments(). putAll (bundle);

    private static void setInspireByDoArguments(DoOptionsFragment fragment, long doId) {
    Bundle bundle = new Bundle();
    bundle.putLong(Constants.EXTRA_DO_ID, doId);
    bundle.putInt(Constants.EXTRA_DO_OPTIONS_DIALOG_MODE, MODE_GET_INSPIRE_BY_DO);
    if (fragment.getArguments() != null) {
        fragment.getArguments().putAll(bundle);
    } else
        fragment.setArguments(bundle);
}

 //This is how I managed to Check if the fragment exist and update the arguments.

 public static void showDoInspireDialog(FragmentManager fragmentManager, long doId, DoOptionsFragment.DoOptionCallBack callBack) {
    DoOptionsFragment doOptionsFragment = (DoOptionsFragment) fragmentManager.findFragmentByTag("do_options_fragment");
    if (doOptionsFragment == null) {
        doOptionsFragment = DoOptionsFragment.getInspiredByDoInstance(doId, callBack);
        fragmentManager.beginTransaction()
                .add(doOptionsFragment, "do_options_fragment")
                .commit();
    } else {
        doOptionsFragment.setCallBack(callBack);
        setInspireByDoArguments(doOptionsFragment, doId);
        doOptionsFragment.showInspireByDoDialog(doId);
    }
}

  public static DoOptionsFragment getInspiredByDoInstance(long doId, DoOptionsFragment.DoOptionCallBack callBack) {
    DoOptionsFragment doOptionsFragment = new DoOptionsFragment();
    setInspireByDoArguments(doOptionsFragment, doId);
    doOptionsFragment.setCallBack(callBack);
    return doOptionsFragment;
}