Насколько плохо вызывать метод активити из фрагмента напрямую?
Есть активити, в которой определен метод "Открыть экран X".
Этот метод определен именно в активити, а не во фрагменте, исходя из того, что его необходимо вызывать при определенном интенте(то есть в onNewIntent перехватываю интент и вызываю этот метод).
Также есть сценарий, когда мне нужно открыть этот же экран X нажав на кнопку в одном из фрагментов. Чтобы не дублировать код метода "Открыть экран X" из активити во фрагмент логичным видится вызов этого метода из фрагмента.
Тут, собственно, вопрос: нужно ли ради этого городить интерфейс с коллбеком чтобы из фрагмента сообщить в активити о необходимости вызвать этот метод или можно просто выполнить ((MyActivity) GetActivity()).openScreenX() ? Насколько плохо так делать и чем чревато? Спасибо
Не вижу в этом ничего плохого, если фрагмент находится в FragmentManager activty и вы придерживаетесь стандартного андроидовского MVC, но надо понимать, что на разных стадиях жизни фрагмента метод getActivity() может вернуть как и ссылку на активити, так и null.
Скажите, а в каких неочевидных для обывателя случаях getActivity() может вернуть null? Ну то есть я вижу это предупреждение даже студия выдает что getActivity() может быть null, мне интересно при каких обстоятельствах может пропасть ссылка на активити?
orbit070, на вскидку пара ситуаций: вызов метода getActivity() в методах onCreate() и onCreateView() при перезапуске активити, к примеру, при смене ориентации экрана, иногда бывает, что вызов onActivityCreated() активити происходит позже создания фрагмента и отработки методов onCreate() и onCreateView(), вторая частая ситуация - вызов этого метода когда фрагмент откреплен (detach). К примеру, у вас во фрагменте есть location listener, который вы не погасили. Фрагмент существует, получает данные геопозиции (или что угодно другое), но уже откреплен и ссылку на активити не отдаст. Вообще, документация скупая, в офф. документации сказано, что getActivity() может выдать null в случаях, когда фрагмент ассоциирован с контекстом, а не с активити.
Спасибо, слышал о таком, но что тогда что сейчас не могу найти примеров реализации такого роутера(наверное неправильно гуглю), все что удается найти это либо Cicerone либо Navigation Architecture Component. Вы не могли бы дать приемлемую на Ваш взгляд ссылку или назвать литературу с описанием создания подобного компонента?
Денис Загаевский, понял, инжектировать - это про даггер? если да то так как с ним не знаком спрошу на всякий случай: если без даггера то мне все эти методы переходов в роутере делать статическими чтобы не создавать везде экземпляры этого класса или как правильно?
orbit070, нет, тогда держишь его в активити и получаешь во фрагментах через интерфейс. Паттерн Service Locator. Но это так себе вариант. Даггер на базовом уровне изучить за день можно. А то и быстрее.
Денис Загаевский, понял, большое спасибо. А в качестве временной затычки пока даггер не внедрю можно например создать экземпляр роутера в активити а во фрагментах его получать так ((MyActivity) GetActivity()).getRouter()? Или это прям очень плохо и делать так не стоит? Тут даже вопрос не только про роутер а вообще интересно - например в Вашем коде можно встретить подобные конструкции? Просто хочется делать правильно а не лишь бы работало, поэтому так расспрашиваю
orbit070, ну это не особо хорошо, повышается связность, появляются лишние знания у компонентов друг о друге, но сделать можно. У нас всё инжектится через даггер, редкие легаси места, где такое есть.
Можно использовать библиотеку EventBus и общаться между компонентами приложения событиями, снижается связность между ними, не важно фрагмент это и активити, или какой то бэкграунд сервис и та же активити