According to the code & javadoc for Fragment.getActivity()
you can get null
returned:
/**
* Return the {@link FragmentActivity} this fragment is currently associated with.
* May return {@code null} if the fragment is associated with a {@link Context}
* instead.
*
* @see #requireActivity()
*/
@Nullable
final public FragmentActivity getActivity() {
return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}
Particularly this could happen when your Fragment is not attached to an activity (as pointed out here and here).
Similarly, getContext()
can also return null.
There's a good discussion on when these can be null on this possibly related post:
The simple solution has been provided already - put in a null check before displaying the Toast
.
But the underlying problem is one of architecture - your code is coupling API activity to your UI, and assuming certain things about your UI state i.e. you are assuming that when the API call returns, your screen is still visible to the user.
A better solution would be to decouple the Retrofit call from the UI - put the API calls in a separate class that does not depend on the UI state.
Use an event or pub-sub framework to communicate from this API wrapper class back to any UI components that need to know when an API call returns.
EventBus
or RxJava
would be 2 common solutions for this (LocalBroadcastManager
would be a less common approach).
This will allow any code to call into your API, and to subscribe to be notified when the API returns.
It also allows you to save your API responses in (for example) a local database, in which case you could just rely on the LiveData
pattern to update any UI that needs to be.
Here's a Medium article giving a brief description of how to use the Android Architecture Components in this manner using the Repository
pattern.
Given that some projects cannot be redesigned immediately, there may be need for workarounds.
The above mentioned null check workaround is useful in that the app will no longer crash. Unfortunately it does mean that the user will not be alerted to the failed API call.
One alternative is to create your own Application
subclass (many projects will already have done this in order to initialise common libraries) and provide a method for static access to this application Context
. (A similar suggestion has subsequently been made by Kushal.)
You could then choose to display the Toast
using the application Context
instead of the one from the fragment. You may lose any specific styling that would have been gained from the more specific context, but the advantage would be that your user still gets to see the Toast
message.
Exposing your Application
as a singleton has been described very nicely on this post: