Search code examples
androidandroid-activityfragment

Is it safe to call `getActivity()` from `onCreateView`?


Looking at the Fragment lifecycle (e.g. here), the Activity seems to be attached to the Fragment before any other callback is issued (this is notified by the onAttach() method).

In my application, which consist of a single activity, the first Fragment is opened from the onCreate() method of the Activity (actually it is the last thing done inside onCreate()).

Currently, I'm initializing all my graphical elements inside the onCreateView() callback, including the instantiation of some object (like an ArrayAdapter) which require the Activity to be constructed, which is obtained calling getActivity(). I assume that the Activity is guaranteed to exist at this point, since the onAttach() method has already been called.
I noticed that IntelliJ warned me about the possibility of getActivity() returning null, maybe just because the method is annotated as @Nullable, so I started to search on the web if my assumption was actually true, and now I'm confused: is it actually safe to call getActivity() inside onCreateView()? Why is there a method called onActivityCreated() (I know it is now deprecated, but it surely served a purpose when it wasn't)?

Unfortunately the documentation does not help to understand this.


Solution

  • As per the official Fragment lifecycle documentation:

    FragmentManager is also responsible for attaching fragments to their host activity and detaching them when the fragment is no longer in use. The Fragment class has two callback methods, onAttach() and onDetach(), that you can override to perform work when either of these events occur.

    So between onAttach() and onDetach(), getActivity() will always return a non-null Activity and that page continues in saying:

    onAttach() is always called before any Lifecycle state changes.

    onDetach() is always called after any Lifecycle state changes.

    So, yes, onCreateView(), being a lifecycle state change, will mean that getActivity() returns a non-null value.

    This is exactly the use case for requireActivity() - it allows you to tell the fragment system that you know at that point in time that getActivity() will return a non-null value and you'd like a compile time guarantee that any code following your requireActivity() call have access to a non-null Activity.

    As for onActivityCreated(), it is an incredibly badly named method as per this answer:

    You have never needed to wait for onActivityCreated() to call requireActivity() or getActivity() - those are both available as soon as the Fragment is attached to the FragmentManager and hence can be used in onAttach(), onCreate(), onCreateView(), onViewCreated() all before onActivityCreated() is called.

    This is one of the reasons why onActivityCreated() was deprecated - it actually has nothing to do with the activity becoming available to the Fragment, nor does it have anything to do with the activity finishing its onCreate() (it, in fact, can be called multiple times - every time the Fragment's view is created, not just once after the first time the Activity finishes onCreate()).

    Of course, note that APIs like ArrayAdapter do not require an Activity - they require a Context. There are similar methods in getContext() and requireContext() that are preferred if you are specifically looking for a Context.