Как из фрагмента передать данные в активити
Перейти к содержимому

Как из фрагмента передать данные в активити

  • автор:

Как из фрагмента передать данные в активити

Одна activity может использовать несколько фрагментов, например, с одной стороны список, а с другой — детальное описание выбранного элемента списка. В такой конфигурации activity использует два фрагмента, которые между собой должны взаимодействовать. Рассмотрим базовые принципы взаимодействия фрагментов в приложении.

Создадим новый проект с пустой MainActivity. Далее создадим разметку layout для фрагментов. Пусть у нас в приложении будет два фрагмента. Добавим в папку res/layout новый xml-файл fragment_list.xml :

Здесь определен элемент ListView для вывода списка объектов.

И также добавим для другого фрагмента файл разметки fragment_detail.xml :

Оба фрагмента будут предельно простыми: один будет содержать список, а второй — текстовой поле. Логика приложения будет такова: при выборе элемента в списке в одном фрагменте выбранный элемент должен отобразиться в текством поле, которое находится во втором фрагменте.

Затем добавим в проект в одну папку с MainActivity собственно классы фрагментов. Добавим новый класс ListFragment со следующим содержимым:

package com.example.fragmentapp; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import androidx.fragment.app.Fragment; public class ListFragment extends Fragment < interface OnFragmentSendDataListener < void onSendData(String data); >private OnFragmentSendDataListener fragmentSendDataListener; String[] countries = < "Бразилия", "Аргентина", "Колумбия", "Чили", "Уругвай">; @Override public void onAttach(Context context) < super.onAttach(context); try < fragmentSendDataListener = (OnFragmentSendDataListener) context; >catch (ClassCastException e) < throw new ClassCastException(context.toString() + " должен реализовывать интерфейс OnFragmentInteractionListener"); >> @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < View view = inflater.inflate(R.layout.fragment_list, container, false); // получаем элемент ListView ListView countriesList = view.findViewById(R.id.countriesList); // создаем адаптер ArrayAdapteradapter = new ArrayAdapter(getContext(), android.R.layout.simple_list_item_1, countries); // устанавливаем для списка адаптер countriesList.setAdapter(adapter); // добавляем для списка слушатель countriesList.setOnItemClickListener(new AdapterView.OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View v, int position, long id) < // получаем выбранный элемент String selectedItem = (String)parent.getItemAtPosition(position); // Посылаем данные Activity fragmentSendDataListener.onSendData(selectedItem); >>); return view; > >

Фрагменты не могут напрямую взаимодействовать между собой. Для этого надо обращаться к контексту, в качестве которого выступает класс Activity. Для обращения к activity, как правило, создается вложенный интерфейс. В данном случае он называется OnFragmentSendDataListener с одним методом.

interface OnFragmentSendDataListener < void onSendData(String data); >private OnFragmentSendDataListener fragmentSendDataListener;

Но чтобы взаимодействовать с другим фрагментом через activity, нам надо прикрепить текущий фрагмент к activity. Для этого в классе фрагмента определен метод onAttach(Context context) . В нем происходит установка объекта OnFragmentSendDataListener :

fragmentSendDataListener = (OnFragmentSendDataListener) context;

При обработке нажатия на элемент в списке мы можем отправить Activity данные о выбранном объекте:

String selectedItem = (String)parent.getItemAtPosition(position); fragmentSendDataListener.onSendData(selectedItem);

Таким образом, при выборе объекта в списке MainActivity получит выбранный объект.

Теперь определим класс для второго фрагмента. Назовем его DetailFragment :

package com.example.fragmentapp; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.fragment.app.Fragment; public class DetailFragment extends Fragment < @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < return inflater.inflate(R.layout.fragment_detail, container, false); >// обновление текстового поля public void setSelectedItem(String selectedItem) < TextView view = getView().findViewById(R.id.detailsText); view.setText(selectedItem); >>

Задача этого фрагмента — вывод некоторой информации. Так как он не должен передавать никакую информацию другому фрагменту, здесь мы модем ограничиться только переопределением метода onCreateView() , который в качестве визуального интерфейса устанавливает разметку из файла fragment_detail.xml

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

В итоге получится следующая структура:

Создание фрагментов в Android

Теперь изменим файл разметки activity_main.xml :

С помощью двух элементов FragmentContainerView в MainActivity добавляются два выше определенных фрагмента.

И в конце изменим код MainActivity :

package com.example.fragmentapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity implements ListFragment.OnFragmentSendDataListener < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >@Override public void onSendData(String selectedItem) < DetailFragment fragment = (DetailFragment) getSupportFragmentManager() .findFragmentById(R.id.detailFragment); if (fragment != null) fragment.setSelectedItem(selectedItem); >>

Для взаимодействия фрагмента ListFragment c другим фрагментом через MainActivity надо, чтобы эта activity реализовывала интерфейс OnFragmentSendDataListener. Для этого реализуем метод onSendData() , который получает фрагмент DetailFragment и вызывает у него метод setSelectedItem()

В итоге получится, что при выборе в списке во фрагменте ListFragment будет срабатывать слушатель списка и в частности его метод onItemClick(AdapterView parent, View v, int position, long id) , который вызовет метод fragmentSendDataListener.onSendData(selectedItem); . fragmentSendDataListener устанавливается как MainActivity, поэтому при этом будет вызван метод setSelectedItem у фрагмента DetailFragment. Таким образом, произойдет взаимодействие между двумя фрагментами.

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

Фрагменты в activity в Android и Java

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

Как отправить данные из Activity в Fragment с подключенным ViewPager2?

Всем привет!
Я пытаюсь отправить данные из MainActivity в один из фрагментов, созданных с помощью ViewPager2.

@Override protected void onCreate(Bundle savedInstanceState)
public class MainPagerAdapter extends FragmentStateAdapter < public MainPagerAdapter(@NonNull FragmentActivity fragmentActivity) < super(fragmentActivity); >@NonNull @Override public Fragment createFragment(int position) < switch (position) < case 0: return new Fragment1(); case 1: return new Fragment2(); default: return new Fragment3(); >> @Override public int getItemCount() < return 3; >>

Отправляю данные из MainActivity так:

Fragment1 fragment1 = new Fragment1(); Bundle bundle = new Bundle(); bundle.putInt("1", 1); fragment1.setArguments(bundle);

И пытаюсь получить их в Fragment:

Bundle bundle = this.getArguments(); if (bundle != null)

Но всегда приходит пустой bundle, потому что фрагмент создаётся только тогда, когда Viewpager перелистывает его.
Как мне отправить данные в Fragment во время создания MainActivity?

  • Вопрос задан более трёх лет назад
  • 542 просмотра

1 комментарий

Средний 1 комментарий

а где код замены фрагмента?
Вы его создаете, но не заменяете
Решения вопроса 2
Денис Загаевский @zagayevskiy Куратор тега Java
Android developer at Yandex

Во время создания активити фрагмент ещё не существует. Ты его, судя по коду, создал, наполнил данными, и потом просто выкинул. Пейджер создал себе новый фрагмент.
Один из путей тут, сделать некий репозиторий с данными, куда активити сложит их, а фрагмент заберёт оттуда, когда ему данные понадобятся. Репозиторий хранить в активити или в графе DI.
Другой путь проще — использовать adapter по назначению. Он, по задумке, адаптирует(превращает) данные во фрагменты. Передай свои данные из активити в адаптер, и при создании фрагмента в адаптере наполняй его этими данными.

Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
dendead @dendead Автор вопроса

Вроде так и получилось)

pagerAdapter = new MainPagerAdapter(this); pagerAdapter.setData(fragment1Container);

В MainPagerAdapter:

public class MainPagerAdapter extends FragmentStateAdapter < private Fragment1Container fragment1Container; private Fragment2Container fragment2Container; public void setData(Fragment1Container container) < f ragment1Container = container; >public void setData(Fragment2Container container) < fragment2Container = container; >@NonNull @Override public Fragment createFragment(int position) < switch (position) < case 0: Fragment1 fragment1 = new Fragment1(); Bundle bundle = new Bundle(); Gson gson = new Gson(); bundle.putString("fragment1Container", gson.toJson(fragment1Container)); fragment1.setArguments(bundle); return fragment1; case 1. 

В Fragment1:

private Fragment1Container fragment1Container; if (bundle != null) < Gson gson = new Gson(); String jsonString = bundle.getString("fragment1Container"); Type entityType = new TypeToken()<>.getType(); fragment1Container = gson.fromJson(jsonString , entityType ); >

Как из фрагмента передать данные в активити

Для передачи данных между двумя Activity используется объект Intent . Через его метод putExtra() можно добавить ключ и связанное с ним значение.

Например, передача из текущей activity в SecondActivity строки "Hello World" с ключом "hello":

// создание объекта Intent для запуска SecondActivity Intent intent = new Intent(this, SecondActivity.class); // передача объекта с ключом "hello" и значением "Hello World" intent.putExtra("hello", "Hello World"); // запуск SecondActivity startActivity(intent);

Для передачи данных применяется метод putExtra() , который в качестве значения позволяет передать данные простейших типов - String, int, float, double, long, short, byte, char, массивы этих типов, либо объект интерфейса Serializable.

Чтобы получить отправленные данные при загрузке SecondActivity, можно воспользоваться методом get() , в который передается ключ объекта:

Bundle arguments = getIntent().getExtras(); String name = arguments.get("hello").toString(); // Hello World

В зависимости от типа отправляемых данных при их получении мы можем использовать ряд методов объекта Bundle. Все они в качестве параметра принимают ключ объекта. Основные из них:

  • get() : универсальный метод, который возвращает значение типа Object. Соответственно поле получения данное значение необходимо преобразовать к нужному типу
  • getString() : возвращает объект типа String
  • getInt() : возвращает значение типа int
  • getByte() : возвращает значение типа byte
  • getChar() : возвращает значение типа char
  • getShort() : возвращает значение типа short
  • getLong() : возвращает значение типа long
  • getFloat() : возвращает значение типа float
  • getDouble() : возвращает значение типа double
  • getBoolean() : возвращает значение типа boolean
  • getCharArray() : возвращает массив объектов char
  • getIntArray() : возвращает массив объектов int
  • getFloatArray() : возвращает массив объектов float
  • getSerializable() : возвращает объект интерфейса Serializable

Пусть у нас в проекте будет определено две activity: MainActivity и SecondActivity.

В коде SecondActivity определим получение данных:

package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class SecondActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); TextView textView = new TextView(this); textView.setTextSize(26); textView.setPadding(16, 16, 16, 16); Bundle arguments = getIntent().getExtras(); if(arguments!=null)< String name = arguments.get("name").toString(); String company = arguments.getString("company"); int age = arguments.getInt("age"); textView.setText("Name: " + name + "\nCompany: " + company + "\nAge: " + age); >setContentView(textView); > >

В данном случае в SecondActivity получаем все данных из объекта Bundle и выводим их в текстовое поле TextView. Предполагается, что данной activity будут передаваться три элемента - две строки с ключами name и company и число с ключом price.

Теперь определим передачу в SecondActivity данных. Например, определим для MainActivity следующий интерфейс в файле activity_main.xml :

Здесь определены три текстовых поля для ввода данных и кнопка.

В классе MainActivity определим следующее содержимое:

package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >public void onClick(View v) < EditText nameText = findViewById(R.id.name); EditText companyText = findViewById(R.id.company); EditText ageText = findViewById(R.id.age); String name = nameText.getText().toString(); String company = companyText.getText().toString(); int age = Integer.parseInt(ageText.getText().toString()); Intent intent = new Intent(this, SecondActivity.class); intent.putExtra("name", name); intent.putExtra("company", company); intent.putExtra("age", age); startActivity(intent); >>

В обработчике нажатия кнопки получаем введенные в текстовые поля EditText данные и передаем их в объект Intent с помощью метода putExtra() . Затем запускаем SecondActivity.

В итоге при нажатии на кнопку запустится SecondActivity, которая получит некоторые введенные в текстовые поля данные.

putExtra in Android и getString in Activity in Android Java

Передача сложных объектов

В примере выше передавались простые данные - числа, строки. Но также мы можем передавать более сложные данные. В этом случае используется механизм сериализации. Для этого нажмем на папку пакета, где находятся классы MainActivity и SecondActivity, правой кнопкой мыши и в контекстном меню выберем New -> Java Class :

Добавление класса Java в Android Studio

Назовем новый класс User - пусть он будет представлять пользователя.

Добавление класса Java в Android и передача сложных объектов в MainActivity

Пусть класс User имеет следующий код:

package com.example.viewapp; import java.io.Serializable; public class User implements Serializable < private String name; private String company; private int age; public User(String name, String company, int age)< this.name = name; this.company = company; this.age = age; >public String getName() < return name; >public void setName(String name) < this.name = name; >public String getCompany() < return company; >public void setCompany(String company) < this.company = company; >public int getAge() < return age; >public void setAge(int age) < this.age = age; >>

Стоит отметить, что данный класс реализует интерфейс Serializable . Теперь изменим код MainActivity:

package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >public void onClick(View v) < EditText nameText = findViewById(R.id.name); EditText companyText = findViewById(R.id.company); EditText ageText = findViewById(R.id.age); String name = nameText.getText().toString(); String company = companyText.getText().toString(); int age = Integer.parseInt(ageText.getText().toString()); User user = new User(name, company, age); Intent intent = new Intent(this, SecondActivity.class); intent.putExtra(User.class.getSimpleName(), user); startActivity(intent); >>

Теперь вместо трех разрозненных данных передается один объект User. В качестве ключа используется результат метода User.class.getSimpleName() , который по сути возвращает название класса.

И изменим класс SecondActivity:

package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class SecondActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); //setContentView(R.layout.activity_second); TextView textView = new TextView(this); textView.setTextSize(26); textView.setPadding(16, 16, 16, 16); Bundle arguments = getIntent().getExtras(); User user; if(arguments!=null)< user = (User) arguments.getSerializable(User.class.getSimpleName()); textView.setText("Name: " + user.getName() + "\nCompany: " + user.getCompany() + "\nAge: " + String.valueOf(user.getAge())); >setContentView(textView); > >

Для получения данных применяется метод getSerializable() , поскольку класс User реализует интерфейс Serializable. Таким образом, мы можем передать один единственый объект вместо набора разрозненных данных.

Урок 106. Android 3. Fragments. Взаимодействие с Activity

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

Для чистоты эксперимента будем работать с двумя фрагментами: статическим и динамическим.

Project name: P1061_FragmentActivity
Build Target: Android 4.1
Application name: FragmentActivity
Package name: ru.startandroid.develop.p1061fragmentactivity
Create Activity: MainActivity

В strings.xml добавим строки:

Fragment 1 Fragment 2 Log Find

Создаем layout и классы для двух фрагментов.

fragment1.xml:

fragment2.xml:

Fragment1.java:

package ru.startandroid.develop.p1061fragmentactivity; import android.app.Fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class Fragment1 extends Fragment < final String LOG_TAG = "myLogs"; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < View v = inflater.inflate(R.layout.fragment1, null); Button button = (Button) v.findViewById(R.id.button); button.setOnClickListener(new OnClickListener() < public void onClick(View v) < Log.d(LOG_TAG, "Button click in Fragment1"); >>); return v; > >

У фрагмента нет привычного для нас метода findViewById для поиска компонентов с экрана. Поэтому вызываем этот метод для View, которое будет содержимым фрагмента. В методе onCreateView мы создаем View и сразу же находим в нем кнопку и ставим ей обработчик. Затем отдаем View системе.

Fragment2.java:

package ru.startandroid.develop.p1061fragmentactivity; import android.app.Fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class Fragment2 extends Fragment < final String LOG_TAG = "myLogs"; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < View v = inflater.inflate(R.layout.fragment2, null); Button button = (Button) v.findViewById(R.id.button); button.setOnClickListener(new OnClickListener() < public void onClick(View v) < Log.d(LOG_TAG, "Button click in Fragment2"); >>); return v; > >

Все аналогично Fragment1.

Настраиваем основное Activity.

Кнопка, компонент fragment, в который помещен Fragment1, и контейнер FrameLayout, в который потом поместим Fragment2.

Обратите внимание на атрибут tools:layout. В нем указан layout-файл, и мы можем на этапе разработки видеть, как будет выглядеть статический фрагмент, когда приложение будет запущено.

Для этого надо нажать правой кнопкой на компоненте fragment, и через пункт Fragment Layout указать нужный layout.

MainActivity.java:

package ru.startandroid.develop.p1061fragmentactivity; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; public class MainActivity extends Activity < @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); Fragment frag2 = new Fragment2(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.add(R.id.fragment2, frag2); ft.commit(); >>

Здесь мы просто добавляем Fragment2 в контейнер.

Все сохраняем, запускаем приложение.

Жмем кнопку Log в первом фрагменте и смотрим лог:

Button click in Fragment1

Жмем Log во втором фрагменте:

Button click in Fragment2

Все ок. Компоненты в фрагментах нашлись и обработчики среагировали на нажатия.

Атрибут onClick, который мы привыкли использовать для кнопки, здесь не прокатит. Указанный в этом атрибуте метод, будет вызван в Activity, а не в фрагменте.

Доступ к фрагменту из Activity

Разберемся, как получить доступ к фрагменту из Activity. Для этого у FragmentManager есть метод findFragmentById, который на вход принимает id компонента fragment (если фрагмент статический) или id контейнера (если динамический).

У нас в main.xml есть кнопка btnFind, вызывающая метод onClick при нажатии. Дорисуем в MainActivity.java метод onClick:

public void onClick(View v)

Используем метод findFragmentById. В первом случае на вход передаем id компонента fragment, т.к. Fragment1 у нас размещен именно так. При поиске Fragment2 указываем id контейнера, в который этот фрагмент был помещен. В результате метод findFragmentById возвращает нам объект Fragment.

Далее мы получаем доступ к его View с помощью метода getView, находим в нем TextView и меняем текст.

Все сохраняем, запускаем. Жмем кнопку Find

Тексты в фрагментах обновились. Тем самым из Activity мы достучались до фрагментов и их компонентов.

На всякий случай проговорю одну вещь из разряда «Спасибо кэп!». Если посмотреть на код MainActivity, то можно заметить, что работая с frag2 в методе onCreate и с frag2 в методе onClick мы работаем с текущим фрагментом Fragment2. Это так и есть. Оба frag2 в итоге будут ссылаться на один объект. Так что, если вы динамически добавили фрагмент, то у вас уже есть ссылка на него, и искать его через findFragmentById вам уже не надо.

Доступ к Activity из фрагмента

Теперь попробуем из фрагмента поработать с Activity. Для этого фрагмент имеет метод getActivity.

Давайте перепишем обработчик кнопки в первом фрагменте. Будем менять текст кнопки btnFind.

Fragment1.java:

package ru.startandroid.develop.p1061fragmentactivity; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class Fragment1 extends Fragment < public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < View v = inflater.inflate(R.layout.fragment1, null); Button button = (Button) v.findViewById(R.id.button); button.setOnClickListener(new OnClickListener() < public void onClick(View v) < ((Button)getActivity().findViewById(R.id.btnFind)).setText("Access from Fragment1"); >>); return v; > >

Получаем Activity методом getActivity, ищем в нем кнопку и меняем текст.

Сохраняем, запускаем. Жмем кнопку в первом фрагменте:

Работает. Из фрагмента мы поменяли компонент Activity.

Обработка в Activity события из фрагмента

Рассмотрим механизм, который описан в хелпе: фрагмент генерирует некое событие и ставит Activity обработчиком.

Например, в Activity есть два фрагмента. Первый – список заголовков статей. Второй – отображает содержимое статьи, выбранной в первом. Мы нажимаем на заголовок статьи в первом фрагменте и получаем содержимое во втором. В этом случае, цель первого фрагмента – передать в Activity информацию о том, что выбран заголовок. А Activity дальше уже сама решает, что делать с этой информацией. Если, например, приложение запущено на планшете в горизонтальной ориентации, то можно отобразить содержимое статьи во втором фрагменте. Если же приложение запущено на смартфоне, то экран маловат для двух фрагментов и надо запускать отдельное Activity со вторым фрагментом, чтобы отобразить статью.

Фишка тут в том, что первому фрагменту неинтересны все эти терзания Activity. Фрагмент – обособленный модуль. Его дело - проинформировать, что выбрана статья такая-то. Ему не надо искать второй фрагмент и работать с ним – это дело Activity.

Тут немного отвлекусь на небольшое лирическое отступление. Модульность, вообще, - очень важная и полезная штука. И ее надо использовать для универсальности, удобности и легкости в понимании работы своих приложений. Но уникальных рецептов, как правильно все организовать, конечно, нет. Каждый делает по-своему. Именно по этим причинам я в своих уроках даю чисто технические вещи про отдельные компоненты и не рассказываю, как организовывать и писать целое приложение. Иначе, форум бы уже ломился от сообщений, что я все делаю не так и надо по-другому, и каждый бы излагал свое видение. И была бы куча споров, где одна сторона говорит, что крокодил зеленый, а другая сторона говорит, что он нифига не зеленый, а длинный ))

Вернемся к уроку. Фрагмент должен сообщить в Activity, что выбрана статья. Для этого он будет вызывать некий метод в Activity. И как нам сообщает хелп, лучший способ тут – это использовать интерфейс, который мы опишем в фрагменте и который затем будет реализован в Activity. Схема известная и распространенная. Давайте реализуем. В нашем приложении никаких статей нет, поэтому будем просто передавать произвольную строку из второго фрагмента в Activity. А Activity уже будет отображать эту строку в первом фрагменте.

Перепишем Fragment2.java:

package ru.startandroid.develop.p1061fragmentactivity; import android.app.Activity; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class Fragment2 extends Fragment < public interface onSomeEventListener < public void someEvent(String s); >onSomeEventListener someEventListener; @Override public void onAttach(Activity activity) < super.onAttach(activity); try < someEventListener = (onSomeEventListener) activity; >catch (ClassCastException e) < throw new ClassCastException(activity.toString() + " must implement onSomeEventListener"); >> final String LOG_TAG = "myLogs"; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < View v = inflater.inflate(R.layout.fragment2, null); Button button = (Button) v.findViewById(R.id.button); button.setOnClickListener(new OnClickListener() < public void onClick(View v) < someEventListener.someEvent("Test text to Fragment1"); >>); return v; > >

Описываем интерфейс onSomeEventListener. В нем метод someEvent, который на вход получает строку. Этот интерфейс будет реализовывать Activity.

В методе onAttach мы на вход получаем Activity, к которому присоединен фрагмент. Мы пытаемся привести это Activity к типу интерфейса onSomeEventListener, чтобы можно было вызывать метод someEvent и передать туда строку. Теперь someEventListener ссылается на Activity.

Далее, в onCreateView, в обработчике кнопки мы вызываем метод someEvent и передаем туда текст. Этот метод будет отработан в Activity.

Теперь меняем Activity.

MainActivity.java:

package ru.startandroid.develop.p1061fragmentactivity; import ru.startandroid.develop.p1061fragmentactivity.Fragment2.onSomeEventListener; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity implements onSomeEventListener < @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); Fragment frag2 = new Fragment2(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.add(R.id.fragment2, frag2); ft.commit(); >@Override public void someEvent(String s) < Fragment frag1 = getFragmentManager().findFragmentById(R.id.fragment1); ((TextView)frag1.getView().findViewById(R.id.textView)).setText("Text from Fragment 2:" + s); >>

Дописываем интерфейс onSomeEventListener к описанию класса.

onCreate без изменений.

Реализуем метод someEvent. Просто ищем первый фрагмент и вставляем туда текст.

Все сохраняем и запускаем. Жмем кнопку во втором фрагменте:

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

На следующем уроке:

- размещаем элементы в ActionBar

Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *