Pull to refresh

Возврат результата выполнения из DialogFragment во Fragment минуя Activity

Development for Android *
Sandbox

Введение


В этой публикации я покажу, как можно передавать события из DialogFrament в вызывающий Fragment минуя Activity.

В официальном Guide по Dialogs есть раздел PassingEvents. В нем рассказано, как вернуть результат работы DialogFragment в вызывающую Activity. Для этого создается дополнительный интерфейс. Activity реализует этот интерфейс, а у DialogFrament есть ссылка на Activity.

Если инициатором вызова DialogFragment является другой Fragment, то в таком подходе нам придется сначала отправить результат в Activity, а потом уже из Activity в заинтересованный в данных Fragment. Отсюда и минусы:
  • Activity знает о деталях реализации фрагмента (сегодня это дополнительный диалог, а завтра можем реализовать все на одном фрагменте);
  • дополнительный код (больше кода = больше возможностей для ошибок).


К счастью, у класса Fragment есть 3 метода, которые позволят реализовать передачу событий из одного фрагмента в другой фрагмент минуя Activity. Это:

Суть метода


Вызывающий фрагмент:
  • с помощью setTargetFragment устанавливает себя в качестве targetFrament и устанавливает requestCode;
  • реализует метод onActivityResult в котором обрабатывает requestCode и resultCode, а также имеет доступ к дополнительным данным через intent.

Вызываемый фрагмент:
  • c помощью getTargetFrament получает ссылку на вызывающий фрагмент;
  • с помощью getTargetRequestCode получает код с которым он был вызыван;
  • вызывает onActivityResult вызывающего фрагмента и передает результаты своего выполнения через resultCode и Intent (для дополнительных).

Ниже пример кода. Для простоты оставил только актуальные для статьи части.

Вызывающий фрагмент:

public class HostFragment extends Fragment {
    private static final int REQUEST_WEIGHT = 1;
     private static final int REQUEST_ANOTHER_ONE = 2;
     public void openWeightPicker() {
        DialogFragment fragment = new WeightDialogFragment();
        fragment.setTargetFragment(this, REQUEST_WEIGHT);
        fragment.show(getFragmentManager(), fragment.getClass().getName());
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            switch (requestCode) {
                case REQUEST_WEIGHT:
                         int weight = data.getIntExtra(WeightDialogFragment.TAG_WEIGHT_SELECTED, -1)
                         //используем полученные результаты
                         //...
                         break;
                    case REQUEST_ANOTHER_ONE:
                        //...
                         break;
                //обработка других requestCode
            }
            updateUI();
        }
    }
}

Вызываемый фрагмент:

public class WeightDialogFragment extends DialogFragment {
     //тэг для передачи результата обратно
    public static final String TAG_WEIGHT_SELECTED = "weight";
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(..., null);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setView(view)
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                             //отправляем результат обратно
                        Intent intent = new Intent();
                        intent.putExtra(TAG_WEIGHT_SELECTED, mNpWeight.getValue());
                        getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
                    }
                });
        return builder.create();
    }

}

Заключение


Перечисленные в начале статьи минусы в таком подходе отсутствуют. Только два взаимодействующих элемента знают друг о друге. Для остальных это уже неизвестные детали реализации.

Мне бы хотелось узнать, о таком варианте реализации еще при изучении официального гида по диалогам. Я же узнал позже благодаря StackOverflow.
Tags:
Hubs:
Total votes 8: ↑7 and ↓1 +6
Views 29K
Comments Comments 15

Please pay attention