Правильный способ закрыть DialogFragment при использовании компонента навигации? - PullRequest
0 голосов
/ 05 апреля 2020

Я использую компонент Навигация, чтобы показать DialogFragment (<dialog...>...</dialog> в navigation.xml) и хочу знать, каков рекомендуемый способ закрыть диалог. Я попробовал себя и получил следующие результаты:

1) dismiss() в DialogFragment: кажется, работает нормально

2) findNavController().navigateUp(): кажется, работает отлично

3) findNavController().navigate(MyDialogFragmentDirections.actionMyDialogFragmentToMyNormalFragment()): работает, но загружает версию целевого назначения fre sh, поэтому в зависимости от варианта использования это может быть не то, что нужно.

Примечание. Мой вариант использования что MyNormalFragment использует MyDialogFragment для получения некоторого ввода, поэтому после показа MyDialogFragment мне нужно вернуться к уже существующему экземпляру MyNormalFragment.

Так что для меня только 1) или 2) правильно. Теперь мне интересно, есть ли разница между 1) и 2)?

1 Ответ

1 голос
/ 05 апреля 2020

И 1), и 2) в конце концов делают одно и то же, но 2) всегда безопаснее.

Когда вы звоните dismiss(), DialogFragment отклоняется, а DialogFragment остановлен (он получает обратный вызов на onStop()). Это вызывает прослушиватель в DialogFragmentNavigator, который затем обновляет состояние NavController, вызывая popBackStack().

dismiss(), однако это асинхронная операция (как видно из исходный код DialogFragment - вы заметите, что он не использует commitNow(), et c). Поэтому, если бы вы проверили, по какому пункту назначения вы находитесь из NavController.getCurrentDestination(), вы бы увидели, что вы все еще находитесь в пункте назначения в диалоговом окне, несмотря на то, что вызвали увольнение.

navigateUp(), с другой рука, идет прямо к NavController. Поскольку в вашем заднем стеке есть другой пункт назначения (тот, что находится под DialogFragment), исходный код NavController показывает, что navigateUp() просто вызывает popBackStack() - та же операция, что была dismiss() в конечном итоге запуск.

Однако, когда NavController управляет операцией, NavController обновляет свое состояние синхронно. Это означает, что сразу после того, как вы позвоните navigateUp(), он обновит свое getCurrentDestination() и внутреннее состояние в дополнение к вызову через DialogFragmentNavigator popBackStack(), то есть то, что вызывает до dismiss() (удаление упомянутого выше наблюдателя для предотвращения двойных увольнений).

Поэтому вызов navigateUp() всегда является более безопасным выбором, поскольку он гарантирует, что NavController синхронно обновляется до правильного состояния, а не полагается на FragmentManager асинхронная синхронизация (что может означать, что в течение этого периода времени из-за мультитача получаются дополнительные события щелчка и т. Д.).

вызов navigate() с действием, которое имеет app:destination на нем будет перемещаться к новому экземпляру пункта назначения, который не подходит для возврата к вашему предыдущему экземпляру.

...