Як передати змінну від Activity до Fragment і повернути її назад?


135

Зараз я роблю додаток для Android, і хочу передати дату між активністю та фрагментом. У моїй діяльності є кнопка, яка відкриває фрагмент: DatePickerFragment.

У своїй діяльності я показую дату, яку хочу змінити фрагментом. Тому я хочу передати дату дату вибору та повернути її назад до активності.

Я спробував багато рішень, але жодне не працює. Простий спосіб передав би аргумент, але це неможливо зробити з фрагментами.


Моя проблема точно така ж, як і ваша. Мені цікаво, чому приклади трактують лише самі фрагменти як "користувачів" вибору дати, а не діяльність, яка їх розпочала.
Клаудіо

Відповіді:


213

Щоб передати інформацію фрагменту , ви встановлюєте Аргументи під час його створення, і ви можете отримати цей аргумент пізніше за методом 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


10
Я думаю, що люди задають це питання знову і знову, це те, що це не дуже добре пояснено в документації.
Майкл Алан Хафф

1
Я все ще плутаюсь щодо того, який метод найкраще використовувати, ваш чи той, що описано нижче, відповів @Elenasys
Yoann Hercouet

Існує новий спосіб обміну даними між фрагментами за допомогою компонентів архітектури (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, вам знадобляться інтерфейси, додаткова інформація: спілкування з іншими фрагментами


2
Як передати користувацький об’єкт? Я використав, Parcelableале це дало меніclass cast exception
гадюка

це рішення не працює для мене, не можу знайти, звідки імпортувати транзакцію
thebeancounter

Добре, якщо ви завантажите фрагмент у свою діяльність, ви можете надсилати значення через пакет, визначений у вашій транзакції. Поясніть, який у вас сценарій?
Хорхесіс

8

завдяки @ ρyaσѕρєя K та Террі ... це мені дуже допомагає та працює чудово

З діяльності ви надсилаєте дані з наміром у вигляді:

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


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

Насолоджуйтесь магією Котліна!


1

Надсилання даних з діяльності у фрагменти, пов’язані 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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.