Безопасно ли е да извикате `getActivity()` от `onCreateView`?

Разглеждайки жизнения цикъл на фрагмента (напр. тук), активността изглежда е прикачен към фрагмента, преди да бъде издадено друго обратно извикване (това се уведомява от метода onAttach()).

В моето приложение, което се състои от една дейност, първият фрагмент се отваря от метода onCreate() на дейността (всъщност това е последното нещо, направено в onCreate()).

В момента инициализирам всички мои графични елементи в onCreateView() обратното извикване, включително инстанцията на някакъв обект (като ArrayAdapter), който изисква да бъде конструирана дейността, която се получава при извикване на getActivity(). Предполагам, че Activity е гарантирано да съществува в този момент, тъй като методът onAttach() вече е извикан.
Забелязах, че IntelliJ ме предупреди за възможността getActivity() да върне null, може би само защото методът е анотиран като @Nullable, така че започнах да търся в мрежата дали предположението ми наистина е вярно и сега съм объркан: всъщност безопасно ли е да се обадя на getActivity() в onCreateView()? Защо има метод, наречен onActivityCreated() (знам, че вече е отхвърлен, но със сигурност е служил на цел, когато не е бил)?

За съжаление документацията не помага да се разбере това.


person gscaparrotti    schedule 23.01.2021    source източник
comment
можете да го извикате вътре в onCreateView(), но за най-добра практика е необходимо да проверите дали getActivity() е нула или не, защото android не знае кога ще откачите фрагмента, така че ще покаже предупреждението, за да предотврати срив.   -  person NehaK    schedule 23.01.2021
comment
да.. но по-добре да използвате requireActivity() за нулева безопасност   -  person Zain    schedule 23.01.2021
comment
@NehaK всъщност възможно ли е да отделите фрагмента, преди да бъде извикан onCreateView?   -  person gscaparrotti    schedule 23.01.2021


Отговори (1)


Според официалната документация за жизнения цикъл на фрагмента:

FragmentManager е отговорен и за прикачването на фрагменти към дейността на хоста и за отделянето им, когато фрагментът вече не се използва. Класът Fragment има два метода за обратно извикване, onAttach() и onDetach(), които можете да замените, за да извършите работа, когато настъпи някое от тези събития.

Така че между onAttach() и onDetach(), getActivity() винаги ще връща ненулево Activity и тази страница продължава с думите:

onAttach() винаги се извиква преди всякакви промени в състоянието на жизнения цикъл.

onDetach() винаги се извиква след всякакви промени в състоянието на жизнения цикъл.

Така че, да, onCreateView(), тъй като е промяна на състоянието на жизнения цикъл, ще означава, че getActivity() връща различна от нула стойност.

Това е точно случаят на използване за requireActivity() - той ви позволява да кажете на системата за фрагменти, че знаете в този момент от време, че getActivity() ще върне ненулева стойност и бихте искали гаранция за време за компилиране че всеки код след вашето requireActivity() повикване има достъп до различна от нула дейност.

Що се отнася до onActivityCreated(), това е невероятно лошо наречен метод според този отговор:

Никога не е трябвало да чакате onActivityCreated() да извика requireActivity() или getActivity() - и двете са достъпни веднага след като фрагментът е прикачен към FragmentManager и следователно може да се използва в onAttach(), onCreate(), onCreateView(), onViewCreated() всички преди да бъде извикан onActivityCreated().

Това е една от причините, поради които onActivityCreated() беше остарял - всъщност няма нищо общо с дейността, която става достъпна за фрагмента, нито има нещо общо с дейността, завършваща своя onCreate() (той всъщност може да бъде извикан многократно - всеки път, когато се създава изгледът на фрагмента, а не само веднъж след първия път, когато дейността приключи onCreate()).

Разбира се, имайте предвид, че API като ArrayAdapter не изискват активност - те изискват Context. Има подобни методи в getContext() и requireContext(), които са предпочитани, ако търсите конкретно Context.

person ianhanniballake    schedule 23.01.2021
comment
Изчерпателен отговор, благодаря. - person gscaparrotti; 24.01.2021