2013-08-15 3 views
27

Я знаю о «newInstance» -Pattern (Best practice for instantiating a new Android Fragment). Но как я могу обновить эти аргументы фрагмента, например, если другой фрагмент изменяет данные?Лучшая практика для обновления аргументов фрагмента?

Я знаю о методах обратного вызова между 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, каждый раз, когда мне нужен этот аргумент.

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

+0

Да. Сколько кодов говорит? Метод oveeriden -'onSaveInstanceState'- с 1 дополнительной строкой и оператором if-else в 'onCreate'? – gunar

+0

Исходные фрагменты дефектов не должны зависеть от других фрагментов – danny117

+0

Как насчет «переписать» аргументы в общедоступном методе этого фрагмента? –

ответ

16

Вы не можете изменить аргументы после того, как его набор и Fragment добавлен в Activity, я использовал подобный подход, который вы определили сами. Сначала я проверил Bundle, переданный в onCreate(), если его не null я использую его, но если его значение null, то я использую аргументы. И я сохраняю все новейшие данные в onSaveInstanceState(). Для получения более подробной информации: Is it possible to pass arguments to a fragment after it's been added to an activity?

+1

Я бы очень рекомендовал, чтобы ОП установил это как ответ, чтобы дать должный кредит. –

4

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

0

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

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

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

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

1

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

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

Предположим, вам нужен фрагмент, которым нужен аргумент operate.We также может написать его

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

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

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

4

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

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

и обновление контента с новым аргументом

+3

Почему синхронизированы? –

+0

да почему синхронизированный б/у? –

0

Incase вы хотите использовать фрагмент, но нужно обновить аргументы, необходимо использовать 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; 
} 
+0

'fragment.setArguments (bundle)' может создавать 'java.lang.IllegalStateException', если вы переключитесь на существующий фрагмент в Activity – StAlex

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