Статьи из цикла

Четвертая часть серии статей про взаимодействие фрагментов и активности.

Все статьи цикла «Взаимодействие между фрагментами и активностью в Android Studio»:

Предыдущая часть Часть 3. Через интерфейсы.

Введение

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

В части 3 были описаны рекомендованные способы через создание слушателей в виде интерфейсов. Но там прописывается много кода и легко запутаться в переплетениях отправках сигналов.

Можно воспользоваться мощным механизмом намерений (Intent). Сразу предупреждаю, что этот способ из разряда «пушки по воробьям»: мы будем сообщения из фрагментов перекидывать через широковещательные сообщения Android. Это очень не хороший способ, но он имеет право на жизнь. Но лучше воспользоваться слушателями-интерфейсами.

Получаем информацию из фрагмента в активности при клике кнопки фрагмента

Задача. При нажатии на кнопку buttonFragment1 в фрагменте текст из editTextFragment1 фрагмента должен отобразится в поле textView активности.

В коде я откатываюсь к точке сохранения 1, про которую я говорил.

Решение. Будем использовать отправку намерений. Фрагмент будет формировать Intent, а активность будет ловить сигнал.

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

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:

public static final String KEY_FROM_FRAGMENT= "text";

BROADCAST_ACTION — это статическая константа, которая позволит нам идентифицировать сигнал. Почему она в отличии от предыдущей так сложно написана? Мы отправляем Intent как широковещательное сообщение. Сообщений в Android много разными сервисами и приложениями. И мало ли как они называют свои намерения. Чтобы не произошло накладок, то в значении переменной используем название пакета приложения (у вас оно будет скорее всего своё):

public static final String BROADCAST_ACTION = "com.example.fragments.Fragment1";

Код фрагмента

Перейдем к активности. Там объявим переменную приемника сообщений:

private BroadcastReceiver broadcastReceiver;

В методе onCreate() активности создадим экземпляр приемника. После укажем приемнику фильтр сообщений через BROADCAST_ACTION. И зарегистрируем приемник в Android:

broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
    }
};

IntentFilter filter = new IntentFilter(Fragment1.BROADCAST_ACTION);
this.registerReceiver(broadcastReceiver, filter);

Не забудем, что нужно приемник будет разрегистрировать:

@Override
public void onDestroy() {
    super.onDestroy();
    this.unregisterReceiver(this.broadcastReceiver);
}

И теперь можем в методе onReceive() прописать код для вытаскивания текста из намерения и вывода текста в textView:

broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String text = intent.getStringExtra(Fragment1.KEY_FROM_FRAGMENT);
        textView.setText(text);
    }
};

Код активности

Полные коды файлов

Полный код MainActivity.java:

package com.example.fragments;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
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
    public void onDestroy() {
        super.onDestroy();
        this.unregisterReceiver(this.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);

        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);

        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();
        }
    }
}

Полный код Fragment1.java:

package com.example.fragments;

import android.content.Intent;
import android.os.Bundle;

import androidx.fragment.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.fragments.Fragment1";

    public Fragment1() {
    }

    public static Fragment1 newInstance(String param1, String param2) {
        Fragment1 fragment = new Fragment1();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_1, 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:

package com.example.fragments;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import android.content.Intent;
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.fragments.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:

package com.example.fragments;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import androidx.fragment.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() {
    }

    public static Fragment1 newInstance(String param1, String param2) {
        Fragment1 fragment = new Fragment1();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_1, 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(MainActivity.KEY_FROM_ACTIVITY);
                textViewFragment1.setText(text);
            }
        };

        IntentFilter filter = new IntentFilter(MainActivity.BROADCAST_ACTION);
        getActivity().getApplicationContext().registerReceiver(broadcastReceiver, filter);

        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        getActivity().getApplicationContext().unregisterReceiver(this.broadcastReceiver);
    }
}

Получившийся результат:

!

Получаем информацию из фрагмента в активности при клике кнопки активности

Задача. При нажатии на кнопку button в активности текст из editTextFragment1 фрагмента должен отобразится в поле textView активности.

В коде я откатываюсь к точке сохранения 1.

Решение. Тут ситуация посложнее. Нужно вначале в кнопке активности button отправить сигнал в фрагмент (отправим пустое намерение), что активность что-то хочет от фрагмента. Фрагмент в ответ считывает текст из editTextFragment1 и отправляет свой сигнал в активность, которая при приеме выводит полученный текст в textView.

То есть у нас будет объединение двух вышеприведенных примеров.

Сразу привожу коды файлов.

Полные коды файлов

Полный код MainActivity.java:

package com.example.fragments;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
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;

    public static final String BROADCAST_ACTION = "com.example.fragments.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) {
                Intent intent = new Intent(BROADCAST_ACTION);
                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(Fragment1.KEY_FROM_FRAGMENT);
                textView.setText(text);
            }
        };

        IntentFilter filter = new IntentFilter(Fragment1.BROADCAST_ACTION);
        this.registerReceiver(broadcastReceiverActivity, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        this.unregisterReceiver(this.broadcastReceiverActivity);
    }
}

Полный код Fragment1.java:

package com.example.fragments;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import androidx.fragment.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 static final String KEY_FROM_FRAGMENT = "text";
    public static final String BROADCAST_ACTION = "com.example.fragments.Fragment1";

    public Fragment1() {
    }

    public static Fragment1 newInstance(String param1, String param2) {
        Fragment1 fragment = new Fragment1();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_1, 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(BROADCAST_ACTION);
                intentToActivity.putExtra(KEY_FROM_FRAGMENT, S);
                getActivity().getApplicationContext().sendBroadcast(intentToActivity);
            }
        };

        IntentFilter filter = new IntentFilter(MainActivity.BROADCAST_ACTION);
        getActivity().getApplicationContext().registerReceiver(broadcastReceiver, filter);

        return view;
    }
}

Получившийся результат:

!

Получаем информацию из активности в фрагменте при клике кнопки фрагмента

Задача. При нажатии на кнопку buttonFragment1 в фрагменте текст из editText главной активности должен отобразится в поле textViewFragment1 фрагмента.

Решение. Поступаем аналогично. Только наши Intent по своему содержимому поменяются и коды обработки приемников.

Сразу привожу полные коды файлов.

Полные коды файлов

Полный код MainActivity.java:

package com.example.fragments;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
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;

    public static final String KEY_FROM_ACTIVITY = "text";
    public static final String BROADCAST_ACTION = "com.example.fragments.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) {

            }
        });

        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 S = editText.getText().toString();

                Intent intentToFragment = new Intent(BROADCAST_ACTION);
                intentToFragment.putExtra(KEY_FROM_ACTIVITY, S);
                getApplicationContext().sendBroadcast(intentToFragment);
            }
        };

        IntentFilter filter = new IntentFilter(Fragment1.BROADCAST_ACTION);
        this.registerReceiver(broadcastReceiver, filter);
    }
}

Полный код Fragment1.java:

package com.example.fragments;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import androidx.fragment.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 static final String BROADCAST_ACTION = "com.example.fragments.Fragment1";

    public Fragment1() {
    }

    public static Fragment1 newInstance(String param1, String param2) {
        Fragment1 fragment = new Fragment1();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_1, 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(BROADCAST_ACTION);
                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(MainActivity.BROADCAST_ACTION);
        getActivity().getApplicationContext().registerReceiver(broadcastReceiver, filter);

        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        getActivity().getApplicationContext().unregisterReceiver(this.broadcastReceiver);
    }
}

Получившийся результат:

!

Следующая часть Часть 5. Несколько фрагментов.<ul><li>Android Studio icon.svg by Google Inc. / (2019-06-07)</li></ul>