Четвертая часть серии статей про взаимодействие фрагментов и активности.
Все статьи цикла «Взаимодействие между фрагментами и активностью в Android Studio»:
- Часть 1. Подготовка
- Часть 2. Простые способы
- Часть 3. Через интерфейсы
- Часть 4. Через интенты
- Часть 5. Несколько фрагментов
Содержание
- Введение
- Получаем информацию из фрагмента в активности при клике кнопки фрагмента
- Получаем информацию из активности в фрагменте при клике кнопки активности
- Получаем информацию из фрагмента в активности при клике кнопки активности
- Получаем информацию из активности в фрагменте при клике кнопки фрагмента
Предыдущая часть Часть 3. Через интерфейсы.
Введение
В части 2 были рассмотрены простые способы взаимодействия между активностью и фрагментом. Но их лучше (кроме первого) никогда не использовать.
В части 3 были описаны рекомендованные способы через создание слушателей в виде интерфейсов. Но там прописывается много кода и легко запутаться в переплетениях отправках сигналов.
Можно воспользоваться мощным механизмом интентов. Сразу предупреждаю, что этот способ из разряда «пушки по воробьям»: мы будем сообщения из фрагментов перекидывать через широковещательные сообщения Android. Это очень не хороший способ, но он имеет право на жизнь. Но лучше воспользоваться слушателями-интерфейсами.
Получаем информацию из фрагмента в активности при клике кнопки фрагмента
Задача. При нажатии на кнопку buttonFragment1 в фрагменте текст из editTextFragment1 фрагмента должен отобразится в поле textView активности.
В коде я откатываюсь к точке сохранения 1, про которую я говорил.
Решение. Будем использовать отправку интентов. Фрагмент будет формировать интент, а активность будет ловить сигнал.
Вначале займемся фрагментом, откуда мы будем отправлять наш сигнал-интент. В клике кнопки пропишем следующий код.
1 2 3 4 5 |
String S = editTextFragment1.getText().toString(); Intent intent = new Intent(BROADCAST_ACTION); intent.putExtra(KEY_FROM_FRAGMENT, S); getActivity().getApplicationContext().sendBroadcast(intent); |
KEY_FROM_FRAGMENT — это статическая константа, которая означает название поля, которое закидываем в Intent.
1 |
public static final String KEY_FROM_FRAGMENT= "text"; |
BROADCAST_ACTION — это статическая константа, которая позволит нам идентифицировать сигнал. Почему она в отличии от предыдущей так сложно написана? Мы отправляем Intent как широковещательное сообщение. Сообщений в Android много разными сервисами и приложениями. И мало ли как они называют свои интенты. Чтобы не произошло накладок, то в значении переменной используем название приложения.
1 |
public static final String BROADCAST_ACTION = "com.example.workwithfragments.Fragment1"; |
Перейдем к активности. Там объявим переменную приемника сообщений.
1 |
private BroadcastReceiver broadcastReceiver; |
В методе onCreate() активности создадим экземпляр приемника. После укажем приемнику фильтр сообщений через BROADCAST_ACTION. И зарегистрируем приемник в Android.
1 2 3 4 5 6 7 8 |
broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { } }; IntentFilter filter = new IntentFilter(Fragment1.BROADCAST_ACTION); this.registerReceiver(broadcastReceiver, filter); |
Не забудем, что нужно приемник будет разрегистрировать.
1 2 3 4 5 |
@Override public void onDestroy() { super.onDestroy(); this.unregisterReceiver(this.broadcastReceiver); } |
И теперь можем в методе onReceive() прописать код для вытаскивания текста из интента и вывода текста в textView.
1 2 3 4 5 6 7 |
broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String text = intent.getStringExtra(Fragment1.KEY_FROM_FRAGMENT); textView.setText(text); } }; |
Полный код MainActivity.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
package com.example.workwithfragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private EditText editText; private TextView textView; private Button button; private FrameLayout fragmentContainer; private FrameLayout fragmentContainer2; private BroadcastReceiver broadcastReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText)findViewById(R.id.editText); textView = (TextView)findViewById(R.id.textView); button = (Button)findViewById(R.id.button); fragmentContainer = (FrameLayout)findViewById(R.id.fragmentContainer); fragmentContainer2 = (FrameLayout)findViewById(R.id.fragmentContainer2); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); if (fragment == null) { fragment = new Fragment1(); fm.beginTransaction() .add(R.id.fragmentContainer, fragment) .commit(); } broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String text = intent.getStringExtra(Fragment1.KEY_FROM_FRAGMENT); textView.setText(text); } }; IntentFilter filter = new IntentFilter(Fragment1.BROADCAST_ACTION); this.registerReceiver(broadcastReceiver, filter); } @Override public void onDestroy() { super.onDestroy(); this.unregisterReceiver(this.broadcastReceiver); } } |
Полный код Fragment1.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package com.example.workwithfragments; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class Fragment1 extends Fragment { private EditText editTextFragment1; private TextView textViewFragment1; private Button buttonFragment1; public static final String KEY_FROM_FRAGMENT = "text"; public static final String BROADCAST_ACTION = "com.example.workwithfragments.Fragment1"; public Fragment1() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_fragment1, container, false); editTextFragment1 = (EditText) view.findViewById(R.id.editTextFragment1); textViewFragment1 = (TextView) view.findViewById(R.id.textViewFragment1); buttonFragment1 = (Button) view.findViewById(R.id.buttonFragment1); buttonFragment1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String S = editTextFragment1.getText().toString(); Intent intent = new Intent(BROADCAST_ACTION); intent.putExtra(KEY_FROM_FRAGMENT, S); getActivity().getApplicationContext().sendBroadcast(intent); } }); return view; } } |
Получаем информацию из активности в фрагменте при клике кнопки активности
Задача. При нажатии на кнопку button в главной активности текст из editText главной активности должен отобразится в поле textViewFragment1 фрагмента.
В коде я откатываюсь к точке сохранения 1.
Решение. Применим тот же подход с интентами, только наоборот.
Сразу приведу коды файлов.
Полный код MainActivity.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package com.example.workwithfragments; import android.content.Intent; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private EditText editText; private TextView textView; private Button button; private FrameLayout fragmentContainer; private FrameLayout fragmentContainer2; public static final String KEY_FROM_ACTIVITY = "text"; public static final String BROADCAST_ACTION = "com.example.workwithfragments.Activity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText)findViewById(R.id.editText); textView = (TextView)findViewById(R.id.textView); button = (Button)findViewById(R.id.button); fragmentContainer = (FrameLayout)findViewById(R.id.fragmentContainer); fragmentContainer2 = (FrameLayout)findViewById(R.id.fragmentContainer2); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String S = editText.getText().toString(); Intent intent = new Intent(BROADCAST_ACTION); intent.putExtra(KEY_FROM_ACTIVITY, S); getApplicationContext().sendBroadcast(intent); } }); FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); if (fragment == null) { fragment = new Fragment1(); fm.beginTransaction() .add(R.id.fragmentContainer, fragment) .commit(); } } } |
Полный код Fragment1.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
package com.example.workwithfragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class Fragment1 extends Fragment { private EditText editTextFragment1; private TextView textViewFragment1; private Button buttonFragment1; private BroadcastReceiver broadcastReceiver; public Fragment1() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_fragment1, container, false); editTextFragment1 = (EditText) view.findViewById(R.id.editTextFragment1); textViewFragment1 = (TextView) view.findViewById(R.id.textViewFragment1); buttonFragment1 = (Button) view.findViewById(R.id.buttonFragment1); buttonFragment1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String text = intent.getStringExtra("text"); textViewFragment1.setText(text); } }; IntentFilter filter = new IntentFilter("com.example.workwithfragments.Activity"); getActivity().getApplicationContext().registerReceiver(broadcastReceiver, filter); return view; } @Override public void onDestroyView() { super.onDestroyView(); getActivity().getApplicationContext().unregisterReceiver(this.broadcastReceiver); } } |
Как вы могли заметить, тут я немного «схалтурил». В строчках
1 |
String text = intent.getStringExtra("text"); |
1 |
IntentFilter filter = new IntentFilter("com.example.workwithfragments.Activity"); |
Получаем информацию из фрагмента в активности при клике кнопки активности
Задача. При нажатии на кнопку button в активности текст из editTextFragment1 фрагмента должен отобразится в поле textView активности.
В коде я откатываюсь к точке сохранения 1.
Решение. Тут ситуация посложнее. Нужно вначале в кнопке активности button отправить сигнал в фрагмент (отправим пустой интент), что активность что-то хочет от фрагмента. Фрагмент в ответ считывает текст из editTextFragment1 и отправляет свой сигнал в активность, которая при приеме выводит полученный текст в textView.
То есть у нас будет объединение двух вышеприведенных примеров.
Сразу привожу коды файлов.
Полный код MainActivity.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
package com.example.workwithfragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private EditText editText; private TextView textView; private Button button; private FrameLayout fragmentContainer; private FrameLayout fragmentContainer2; private BroadcastReceiver broadcastReceiverActivity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText) findViewById(R.id.editText); textView = (TextView) findViewById(R.id.textView); button = (Button) findViewById(R.id.button); fragmentContainer = (FrameLayout) findViewById(R.id.fragmentContainer); fragmentContainer2 = (FrameLayout) findViewById(R.id.fragmentContainer2); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.workwithfragments.Activity"); getApplicationContext().sendBroadcast(intent); } }); FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); if (fragment == null) { fragment = new Fragment1(); fm.beginTransaction() .add(R.id.fragmentContainer, fragment) .commit(); } broadcastReceiverActivity = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String text = intent.getStringExtra("text"); textView.setText(text); } }; IntentFilter filter = new IntentFilter("com.example.workwithfragments.Fragment1"); this.registerReceiver(broadcastReceiverActivity, filter); } @Override public void onDestroy() { super.onDestroy(); this.unregisterReceiver(this.broadcastReceiverActivity); } } |
Полный код Fragment1.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
package com.example.workwithfragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class Fragment1 extends Fragment { private EditText editTextFragment1; private TextView textViewFragment1; private Button buttonFragment1; private BroadcastReceiver broadcastReceiver; public Fragment1() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_fragment1, container, false); editTextFragment1 = (EditText) view.findViewById(R.id.editTextFragment1); textViewFragment1 = (TextView) view.findViewById(R.id.textViewFragment1); buttonFragment1 = (Button) view.findViewById(R.id.buttonFragment1); buttonFragment1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String S = editTextFragment1.getText().toString(); Intent intentToActivity = new Intent("com.example.workwithfragments.Fragment1"); intentToActivity.putExtra("text", S); getActivity().getApplicationContext().sendBroadcast(intentToActivity); } }; IntentFilter filter = new IntentFilter("com.example.workwithfragments.Activity"); getActivity().getApplicationContext().registerReceiver(broadcastReceiver, filter); return view; } @Override public void onDestroyView() { super.onDestroyView(); getActivity().getApplicationContext().unregisterReceiver(this.broadcastReceiver); } } |
Получаем информацию из активности в фрагменте при клике кнопки фрагмента
Задача. При нажатии на кнопку buttonFragment1 в фрагменте текст из editText главной активности должен отобразится в поле textViewFragment1 фрагмента.
Решение. Поступаем аналогично. Только наши Intent по своему содержимому поменяются и коды обработки приемников.
Полный код MainActivity.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package com.example.workwithfragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private EditText editText; private TextView textView; private Button button; private FrameLayout fragmentContainer; private FrameLayout fragmentContainer2; private BroadcastReceiver broadcastReceiverActivity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText) findViewById(R.id.editText); textView = (TextView) findViewById(R.id.textView); button = (Button) findViewById(R.id.button); fragmentContainer = (FrameLayout) findViewById(R.id.fragmentContainer); fragmentContainer2 = (FrameLayout) findViewById(R.id.fragmentContainer2); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); if (fragment == null) { fragment = new Fragment1(); fm.beginTransaction() .add(R.id.fragmentContainer, fragment) .commit(); } broadcastReceiverActivity = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String S = editText.getText().toString(); Intent intentToFragment = new Intent("com.example.workwithfragments.Activity"); intentToFragment.putExtra("text", S); getApplicationContext().sendBroadcast(intentToFragment); } }; IntentFilter filter = new IntentFilter("com.example.workwithfragments.Fragment1"); this.registerReceiver(broadcastReceiverActivity, filter); } @Override public void onDestroy() { super.onDestroy(); this.unregisterReceiver(this.broadcastReceiverActivity); } } |
Полный код Fragment1.java.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
package com.example.workwithfragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class Fragment1 extends Fragment { private EditText editTextFragment1; private TextView textViewFragment1; private Button buttonFragment1; private BroadcastReceiver broadcastReceiver; public Fragment1() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_fragment1, container, false); editTextFragment1 = (EditText) view.findViewById(R.id.editTextFragment1); textViewFragment1 = (TextView) view.findViewById(R.id.textViewFragment1); buttonFragment1 = (Button) view.findViewById(R.id.buttonFragment1); buttonFragment1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intentToActivity = new Intent("com.example.workwithfragments.Fragment1"); getActivity().getApplicationContext().sendBroadcast(intentToActivity); } }); broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String text = intent.getStringExtra("text"); textViewFragment1.setText(text); } }; IntentFilter filter = new IntentFilter("com.example.workwithfragments.Activity"); getActivity().getApplicationContext().registerReceiver(broadcastReceiver, filter); return view; } @Override public void onDestroyView() { super.onDestroyView(); getActivity().getApplicationContext().unregisterReceiver(this.broadcastReceiver); } } |
Следующая часть Часть 5. Несколько фрагментов.