Как передать переменную из Activity во Fragment и вернуть ее обратно?

135

В настоящее время я делаю приложение для Android и хочу передать дату между активностью и фрагментом. В моей активности есть кнопка, которая открывает фрагмент: DatePickerFragment.

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

Я перепробовал много решений, но ни одно из них не работает. Простой способ передать аргумент, но это не может быть сделано с фрагментами.

Евгений Примако
источник
Моя проблема точно такая же, как ваша. Интересно, почему в примерах рассматриваются только сами фрагменты как «пользователи» средства выбора даты, а не деятельность, которая их начала.
Клаудио

Ответы:

213

Чтобы передать информацию фрагменту , вы устанавливаете Arguments при его создании, и вы можете получить этот аргумент позже с помощью метода onCreate или onCreateView вашего фрагмента.

В функции newInstance вашего фрагмента вы добавляете аргументы, которые хотите отправить ему:

/**
 * Create a new instance of DetailsFragment, initialized to
 * show the text at 'index'.
 */
public static DetailsFragment newInstance(int index) {
    DetailsFragment f = new DetailsFragment();
    // Supply index input as an argument.
    Bundle args = new Bundle();
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}

Затем внутри фрагмента метода onCreateили onCreateViewвы можете получить аргументы, подобные этому:

Bundle args = getArguments();
int index = args.getInt("index", 0);

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

Учебное пособие по документации:

http://developer.android.com/training/basics/fragments/communicating.html

jpardogo
источник
10
Я думаю, что смысл людей, задающих этот вопрос снова и снова, заключается в том, что он не очень хорошо объяснен в документации.
Майкл Алан Хафф
1
Я все еще не понимаю, какой метод лучше использовать, ваш или тот, который указан ниже @Elenasys
Йоанн Херкуэ
Существует новый способ обмена данными между фрагментами с использованием компонентов архитектуры (I / O '17): developer.android.com/topic/libraries/architecture/…
jpardogo
Как насчет тех фрагментов, которые созданы внутри макета XML?
ralphgabb
Я не хочу больше использовать статический метод.
Ахамадулла Сайкат
89

Отправка данных из ActivityвFragment

Деятельность:

Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();

Фрагмент:

Чтение значения во фрагменте

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    String myValue = this.getArguments().getString("message");
    ...
    ...
    ...
}

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

Jorgesys
источник
2
Как передать пользовательский объект? Я использовал, Parcelableно это дало мнеclass cast exception
гадюка
это решение не работает для меня, не могу найти, где импортировать транзакцию
thebeancounter
Хорошо, если вы загрузите фрагмент в свою активность, вы можете отправлять значения через пакет, определенный в вашей транзакции. Объясните, каков ваш сценарий?
Jorgesys
8

спасибо @ ρяσѕρєя K и Терри ... это мне очень помогает и отлично работает

Из Activity вы отправляете данные с намерением:

Bundle bundle = new Bundle(); 
bundle.putString("edttext", "From Activity"); 
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

и в методе Fragment onCreateView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // get arguments
    String strtext = getArguments().getString("edttext");    
    return inflater.inflate(R.layout.fragment, container, false);
}

ссылка: отправить данные из деятельности на фрагмент в Android

Махмуд Захер
источник
7

Используйте библиотеку EventBus для передачи события, которое может содержать вашу переменную, туда и обратно. Это хорошее решение, потому что оно держит ваши действия и фрагменты слабо связаны

https://github.com/greenrobot/EventBus

SemaphoreMetaphor
источник
4
Я не могу сказать, что это не очень хорошее решение, но есть предостережение. Хотя EventBus чрезвычайно прост в использовании, в этом и заключается его опасность. Если вы начнете добавлять слишком много сигналов, слабосвязанная природа может очень усложнить отслеживание того, кто звонит, кому и где происходят различные события.
Йохан Пол
2

Для всех разработчиков Kotlin там:

Вот предлагаемое Android Studio решение для отправки данных в ваш фрагмент (= когда вы создаете пустой фрагмент с помощью файла -> Новый -> Фрагмент -> Фрагмент (пустой) и вы отмечаете «включить методы фабрики фрагментов»).

Поместите это в свой фрагмент:

class MyFragment: Fragment {

...

    companion object {

            @JvmStatic
            fun newInstance(isMyBoolean: Boolean) = MyFragment().apply {
                arguments = Bundle().apply {
                    putBoolean("REPLACE WITH A STRING CONSTANT", isMyBoolean)
                }
            }
     }
}

.applyхороший прием для установки данных при создании объекта или в том виде, в каком они здесь указаны :

Вызывает указанную функцию [блок] со thisзначением в качестве получателя и возвращает thisзначение.

Затем в своей деятельности или фрагменте выполните:

val fragment = MyFragment.newInstance(false)
... // transaction stuff happening here

и прочитайте Аргументы в вашем Фрагменте, такие как:

private var isMyBoolean = false

override fun onAttach(context: Context?) {
    super.onAttach(context)
    arguments?.getBoolean("REPLACE WITH A STRING CONSTANT")?.let {
        isMyBoolean = it
    }
}

Чтобы «отправить» данные обратно в свою активность , просто определите функцию в своей активности и выполните следующие действия в своем фрагменте:

(activity as? YourActivityClass)?.callYourFunctionLikeThis(date) // your function will not be called if your Activity is null or is a different Class

Наслаждайтесь магией Kotlin!

Пол Спизбергер
источник
1

Отправка данных из Activity во фрагменты, связанные с помощью XML

Если вы создаете фрагмент в Android Studio с помощью одного из шаблонов, например, «Файл»> «Создать»> «Фрагмент»> «Фрагмент (список)», этот фрагмент связывается с помощью XML. Метод newInstance создается во фрагменте, но никогда не вызывается, поэтому его нельзя использовать для передачи аргументов.

Вместо этого в Activity переопределите метод onAttachFragment

@Override
public void onAttachFragment(Fragment fragment) {
    if (fragment instanceof DetailsFragment) {
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);        
     }
}

Затем прочитайте аргументы в методе фрагмента onCreate согласно другим ответам

Дол
источник
0

Вы можете просто создать свой фрагмент с помощью пакета:

Fragment fragment = Fragment.instantiate(this, RolesTeamsListFragment.class.getName(), bundle);
Stef
источник