Android Activity refernce getting null on low memory - android

I have an activity that contains a fragment , and this fragment plays youtube videos using android youtube api and I register an event listener for the youtube video when it finishes.
On the onVideoEnded event I get a reference to the activity to do something some action and this is how I get the activity inside my fragment :
private Activity theActivity;
#Override
public void onAttach(Context context) {
super.onAttach(context);
theActivity = (Activity) context;
}
/*
* Deprecated on API 23
* Use onAttachToContext instead
*/
#SuppressWarnings("deprecation")
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (Build.VERSION.SDK_INT < 23) {
theActivity = activity;
}
}
#Override
public void onDetach() {
super.onDetach();
theActivity = null;
}
protected Activity getTheActivity() {
Activity activity = getActivity();
if (activity != null)
return activity;
else return this.theActivity;
}
As you can see on my getTheActivity method I check first the getActivity method , and if it returns a null value , I get the variable I got from onAttach when the fragment was created.
However on devices like samsung getTheActivity method still returns null !
I think it's probably a low memory issue !
How can I get a reference to my activity under any circumstances from my fragment ?

Add these two lines in your manifest file in the application tag
android:hardwareAccelerated="false"
android:largeHeap="true"

Related

Null activity in Fragment even when setting in onAttach()

I have code that looks like this:
(Note: Notice the line at the bottom where I get reports of a NullPointerException. Also, this has been heavily edited for this posting but I believe all of the relevant code is included)
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
public SettingsActivity activity;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity) {
activity = (SettingsActivity) context;
}
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String prefKey) {
// The line below gets many NullPointerException reports
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(activity);
}
}
I thought by setting the activity variable in onAttach() would almost assure that is is not null. (instead of using getActivity())
The instances I have of getActivity() have 0 reports of ever being null. It seems I just need to use that instead. But I would like to know how activity is null and is changing it to getActivity() the way to go?
FWIW, I am not using a onDetach() in this class.
Just a guess: It seems to me that onAttach() can be called well before onSharedPreferenceChanged() might be called, so maybe the activity becomes null by then?
There is always the possibility the activity variable is not null and it is something else in that line, but this seems to be the most obvious to me?
You should use
#Override
public void onAttach (Activity activity) {
super.onAttach(activity)
}
instead
#Override
public void onAttach (Context context) {
super.onAttach(context)
}
Althought the first function was deprecated but it still work as well. Let try.

Android Fragment - getActivity().runOnUiThread returns null when restarting app

when I start the app the first time the code below works just fine. But when leaving the app and opening it again I get an error saying getActivity() returns null.
I'm doing this code in a Fragment:
(getActivity()).runOnUiThread(new Runnable() {
#Override
public void run() {
enableMenu();
openMenu();
navigateToFragment(new BlankFragment());
}
});
What to do ?
How can I get the Activity ?
Create object of Activity and assign that on the onAttach Method like below.
Some times getActivity gives null so its a better way to make activity instance in onAttach and use that instance.
private Activity mActivity;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
Now use this object instead of the getActivity()
The method onAttach(Activity activity) is now deprecated.
You should use this one:
#Override
public void onAttach(Context context) {
super.onAttach(context);
activity = getActivity();
}

Android Fragment onAttach() deprecated

I have updated my app to use the latest support library (version 23.0.0), I've found out that they deprecated the onAttach() function of the Fragment class.
Instead of:
onAttach (Activity activity)
It's now:
onAttach (Context context)
As my app uses the activity passed before deprecation, a possible solution i think is:
#Override
public void onAttach(Context context) {
super.onAttach(context);
activity = getActivity();
}
Would that be the correct way to do it?
UPDATE:
If i run a device with API lower than 23, the new onAttach() is not even being called. I hope that this is not what they intended to do!
UPDATE 2:
Issue has been resolved with the latest updates to the SDK.
I have tested on my API 22 device and onAttach(Context) is being called.
Click here to follow the bug report I've opened a couple of weeks ago and the answers from the guys at Google.
Activity is a context so if you can simply check the context is an Activity and cast it if necessary.
#Override
public void onAttach(Context context) {
super.onAttach(context);
Activity a;
if (context instanceof Activity){
a=(Activity) context;
}
}
Update: Some are claiming that the new Context override is never called. I have done some tests and cannot find a scenario where this is true and according to the source code, it should never be true. In all cases I tested, both pre and post SDK23, both the Activity and the Context versions of onAttach were called. If you can find a scenario where this is not the case, I would suggest you create a sample project illustrating the issue and report it to the Android team.
Update 2: I only ever use the Android Support Library fragments as bugs get fixed faster there. It seems the above issue where the overrides do not get called correctly only comes to light if you use the framework fragments.
This is another great change from Google ... The suggested modification: replace onAttach(Activity activity) with onAttach(Context context) crashed my apps on older APIs since onAttach(Context context) will not be called on native fragments.
I am using the native fragments (android.app.Fragment) so I had to do the following to make it work again on older APIs (< 23).
Here is what I did:
#Override
public void onAttach(Context context) {
super.onAttach(context);
// Code here
}
#SuppressWarnings("deprecation")
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Code here
}
}
If you use the the framework fragments and the SDK version of the device is lower than 23, OnAttach(Context context) wouldn't be called.
I use support fragments instead, so deprecation is fixed and onAttach(Context context) always gets called.
Currently from the onAttach Fragment code, it is not clear if the Context is the current activity: Source Code
public void onAttach(Context context) {
mCalled = true;
final Activity hostActivity = mHost == null ? null : mHost.getActivity();
if (hostActivity != null) {
mCalled = false;
onAttach(hostActivity);
}
}
If you will take a look at getActivity you will see the same call
/**
* Return the Activity this fragment is currently associated with.
*/
final public Activity getActivity() {
return mHost == null ? null : mHost.getActivity();
}
So If you want to be sure that you are getting the Activity then use getActivity() (in onAttach in your Fragment) but don't forget to check for null because if mHost is null your activity will be null
#Override
public void onAttach(Context context) {
super.onAttach(context);
Activity activity = context instanceof Activity ? (Activity) context : null;
}
Although it seems that in most cases it's enough to have onAttach(Context), there are some phones (i.e: Xiaomi Redme Note 2) where it's not being called, thus it causes NullPointerExceptions. So to be on the safe side I suggest to leave the deprecated method as well:
// onAttach(Activity) is necessary in some Xiaomi phones
#SuppressWarnings("deprecation")
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
_onAttach(activity);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
_onAttach(context);
}
private void _onAttach(Context context) {
// do your real stuff here
}
Download newest Support library with the sdk manager and include
compile 'com.android.support:appcompat-v7:23.1.1'
in gradle.app and set compile version to api 23
The answer below is related to this deprecation warning occurring in the Fragments tutorial on the Android developer website and may not be related to the posts above.
I used this code on the tutorial lesson and it did worked.
public void onAttach(Context context){
super.onAttach(context);
Activity activity = getActivity();
I was worried that activity maybe null as what the documentation states.
getActivity
FragmentActivity getActivity ()
Return the FragmentActivity this fragment is currently associated with. May return null if the fragment is associated with a Context instead.
But the onCreate on the main_activity clearly shows that the fragment was loaded and so after this method, calling get activity from the fragment will return the main_activity class.
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
I hope I am correct with this. I am an absolute newbie.
you are probably using android.support.v4.app.Fragment. For this instead of onAttach method, just use getActivity() to get the FragmentActivity with which the fragment is associated with. Else you could use onAttach(Context context) method.
This worked for me when i have userdefined Interface 'TopSectionListener', its object activitycommander:
//This method gets called whenever we attach fragment to the activity
#Override
public void onAttach(Context context) {
super.onAttach(context);
Activity a=getActivity();
try {
if(context instanceof Activity)
this.activitycommander=(TopSectionListener)a;
}catch (ClassCastException e){
throw new ClassCastException(a.toString());}
}

Fragment's reference to mActivity becomes null after orientation change. Ineffective fragment state maintenance

My application consists of several fragments. Up until now I've had references to them stored in a custom Application object, but I am beginning to think that I'm doing something wrong.
My problems started when I realized that all my fragment's references to mActivity becomes null after an orientation change. So when I call getActivity() after an orientation change, a NullPointerException is thrown.
I have checked that my fragment's onAttach() is called before I make the call to getActivity(), but it still returns null.
The following is a stripped version of my MainActivity, which is the only activity in my application.
public class MainActivity extends BaseActivity implements OnItemClickListener,
OnBackStackChangedListener, OnSlidingMenuActionListener {
private ListView mSlidingMenuListView;
private SlidingMenu mSlidingMenu;
private boolean mMenuFragmentVisible;
private boolean mContentFragmentVisible;
private boolean mQuickAccessFragmentVisible;
private FragmentManager mManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* Boolean variables indicating which of the 3 fragment slots are visible at a given time
*/
mMenuFragmentVisible = findViewById(R.id.menuFragment) != null;
mContentFragmentVisible = findViewById(R.id.contentFragment) != null;
mQuickAccessFragmentVisible = findViewById(R.id.quickAccessFragment) != null;
if(!savedInstanceState != null) {
if(!mMenuFragmentVisible && mContentFragmentVisible) {
setupSlidingMenu(true);
} else if(mMenuFragmentVisible && mContentFragmentVisible) {
setupSlidingMenu(false);
}
return;
}
mManager = getSupportFragmentManager();
mManager.addOnBackStackChangedListener(this);
final FragmentTransaction ft = mManager.beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if (!mMenuFragmentVisible && mContentFragmentVisible) {
/*
* Only the content fragment is visible, will enable sliding menu
*/
setupSlidingMenu(true);
onToggle();
ft.replace(R.id.contentFragment, getCustomApplication().getSportsFragment(), SportsFragment.TAG);
} else if (mMenuFragmentVisible && mContentFragmentVisible) {
setupSlidingMenu(false);
/*
* Both menu and content fragments are visible
*/
ft.replace(R.id.menuFragment, getCustomApplication().getMenuFragment(), MenuFragment.TAG);
ft.replace(R.id.contentFragment, getCustomApplication().getSportsFragment(), SportsFragment.TAG);
}
if (mQuickAccessFragmentVisible) {
/*
* The quick access fragment is visible
*/
ft.replace(R.id.quickAccessFragment, getCustomApplication().getQuickAccessFragment());
}
ft.commit();
}
private void setupSlidingMenu(boolean enable) {
/*
* if enable is true, enable sliding menu, if false
* disable it
*/
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// launch the fragment that was clicked from the menu
}
#Override
public void onBackPressed() {
// Will let the user press the back button when
// the sliding menu is open to display the content.
if (mSlidingMenu != null && mSlidingMenu.isMenuShowing()) {
onShowContent();
} else {
super.onBackPressed();
}
}
#Override
public void onBackStackChanged() {
/*
* Change selected position when the back stack changes
*/
if(mSlidingMenuListView != null) {
mSlidingMenuListView.setItemChecked(getCustomApplication().getSelectedPosition(), true);
}
}
#Override
public void onToggle() {
if (mSlidingMenu != null) {
mSlidingMenu.toggle();
}
}
#Override
public void onShowContent() {
if (mSlidingMenu != null) {
mSlidingMenu.showContent();
}
}
}
The following is a stripped version of the CustomApplication. My thoughts behind this implementation was to guarantee only one instance of each fragment throughout my application's life cycle.
public class CustomApplication extends Application {
private Fragment mSsportsFragment;
private Fragment mCarsFragment;
private Fragment mMusicFragment;
private Fragment mMoviesFragment;
public Fragment getSportsFragment() {
if(mSsportsFragment == null) {
mSsportsFragment = new SportsFragment();
}
return mSsportsFragment;
}
public Fragment getCarsFragment() {
if(mCarsFragment == null) {
mCarsFragment = new CarsFragment();
}
return mCarsFragment;
}
public Fragment getMusicFragment() {
if(mMusicFragment == null) {
mMusicFragment = new MusicFragment();
}
return mMusicFragment;
}
public Fragment getMoviesFragment() {
if(mMoviesFragment == null) {
mMoviesFragment = new MoviesFragment();
}
return mMoviesFragment;
}
}
I am very interested in tips on how to best implement multiple fragments and how to maintain their states. For your information, my applicaion consists of 15+ fragments so far.
I have done some research and it seems that FragmentManager.findFragmentByTag() is a good bet, but I haven't been able to successfully implement it.
My implementation seems to work good except for the fact that mActivity references become null after orientation changes, which lets me to believe that I may have some memory leak issues as well.
If you need to see more code, please let me know. I purposely avoided including fragment code as I strongly believe issues are related to my Activity and Application implementations, but I may be wrong.
Thanks for your time.
My thoughts behind this implementation was to guarantee only one instance of each fragment throughout my application's life cycle
This is probably part, if not all, of the source of your difficulty.
On a configuration change, Android will re-create your fragments by using the public zero-argument constructor to create a new instance. Hence, your global-scope fragments will not "guarantee only one instance of each fragment".
Please delete this custom Application class. Please allow the fragments to be re-created naturally, or if they need to live for the life of a single activity, use setRetainInstance(true). Do not attempt to reuse fragments across activities.
I don't see where are you using the reference to mActivity. But don't hold a reference to it. Always use getActivity since the Activity can be recreated after orientation change. Also, don't ever set the fragment's fields by setters or by assigning always use a Bundle and Arguments
Best practice for instantiating a new Android Fragment
Also you can use setRetainInstance(true) to keep all the fragment's members during orientation change.
Understanding Fragment's setRetainInstance(boolean)
To resolve this problem you have to use the activity object provided by onAttach method of fragment so when you change the orientation fragment is recreated so onAttach give you the current reference
you can use onAttach(Context context) to create a private context variable in fragment like this
#Override
public void onAttach(Context context) {
this.context = context;
super.onAttach(context);
}
on changing orientation, onAttach gives you new reference to the context, if you want reference to activity, you can typecast context to activity.
Context can also be reassigned inside onCreate in fragments as OnCreate is called when device is rotated
private Context mContext;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//get new activity reference here
mContext = getActivity();
}
pass this mContext throughout the fragment
If you don't setRetainInstance(true) in onCreate ... the collection e.g List<Object>, Vector<Object> in Application class will get null. Make sure you setRetainInstance(true) to make them alive.

getActivity() returns null in Fragment function

I have a fragment (F1) with a public method like this
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
and yes when I call it (from the Activity), it is null...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
It must be something that I am doing very wrong, but I don't know what that is.
commit schedules the transaction, i.e. it doesn't happen straightaway but is scheduled as work on the main thread the next time the main thread is ready.
I'd suggest adding an
onAttach(Activity activity)
method to your Fragment and putting a break point on it and seeing when it is called relative to your call to asd(). You'll see that it is called after the method where you make the call to asd() exits. The onAttach call is where the Fragment is attached to its activity and from this point getActivity() will return non-null (nb there is also an onDetach() call).
The best to get rid of this is to keep activity reference when onAttach is called and use the activity reference wherever needed, for e.g.
#Override
public void onAttach(Context context) {
super.onAttach(activity);
mContext = context;
}
#Override
public void onDetach() {
super.onDetach();
mContext = null;
}
This happened when you call getActivity() in another thread that finished after the fragment has been removed. The typical case is calling getActivity() (ex. for a Toast) when an HTTP request finished (in onResponse for example).
To avoid this, you can define a field name mActivity and use it instead of getActivity(). This field can be initialized in onAttach() method of Fragment as following:
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity){
mActivity =(Activity) context;
}
}
In my projects, I usually define a base class for all of my Fragments with this feature:
public abstract class BaseFragment extends Fragment {
protected FragmentActivity mActivity;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity){
mActivity =(Activity) context;
}
}
}
Happy coding,
The other answers that suggest keeping a reference to the activity in onAttach are just suggesting a bandaid to the real problem. When getActivity returns null it means that the Fragment is not attached to the Activity. Most commonly this happens when the Activity has gone away due to rotation or the Activity being finished but the Fragment still has some kind of callback listener registered preventing it from being garbage collected. When the listener gets called if you need to do something with the Activity but the Activity is gone there isn't much you can do. In your code you should just check getActivity() != null and if it's not there then don't do anything. If you keep a reference to the Activity that is gone you are preventing the Activity from being garbage collected. Any UI things you might try to do won't be seen by the user. I can imagine some situations where in the callback listener you want to have a Context for something non-UI related, in those cases it probably makes more sense to get the Application context. Note that the only reason that the onAttach trick isn't a big memory leak is because normally after the callback listener executes it won't be needed anymore and can be garbage collected along with the Fragment, all its View's and the Activity context. If you setRetainInstance(true) there is a bigger chance of a memory leak because the Activity field will also be retained but after rotation that could be the previous Activity not the current one.
Since Android API level 23, onAttach(Activity activity) has been deprecated. You need to use onAttach(Context context). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
Activity is a context so if you can simply check the context is an Activity and cast it if necessary.
#Override
public void onAttach(Context context) {
super.onAttach(context);
Activity a;
if (context instanceof Activity){
a=(Activity) context;
}
}
PJL is right.
I have used his suggestion and this is what i have done:
defined global variables for fragment:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
implemented
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
synchronized (attachingActivityLock) {
syncVariable = true;
attachingActivityLock.notifyAll();
}
}
3 . I wrapped up my function, where I need to call getActivity(), in thread, because if it would run on main thread, i would block the thread with the step 4. and onAttach() would never be called.
Thread processImage = new Thread(new Runnable() {
#Override
public void run() {
processImage();
}
});
processImage.start();
4 . in my function where I need to call getActivity(), I use this (before the call getActivity())
synchronized (attachingActivityLock) {
while(!syncVariable){
try {
attachingActivityLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
If you have some UI updates, remember to run them on UI thread. I need to update ImgeView so I did:
image.post(new Runnable() {
#Override
public void run() {
image.setImageBitmap(imageToShow);
}
});
The order in which the callbacks are called after commit():
Whatever method you call manually right after commit()
onAttach()
onCreateView()
onActivityCreated()
I needed to do some work that involved some Views, so onAttach() didn't work for me; it crashed. So I moved part of my code that was setting some params inside a method called right after commit() (1.), then the other part of the code that handled view inside onCreateView() (3.).
I am using OkHttp and I just faced this issue.
For the first part #thucnguyen was on the right track.
This happened when you call getActivity() in another thread that finished after the fragment has been removed. The typical case is calling getActivity() (ex. for a Toast) when an HTTP request finished (in onResponse for example).
Some HTTP calls were being executed even after the activity had been closed (because it can take a while for an HTTP request to be completed). I then, through the HttpCallback tried to update some Fragment fields and got a null exception when trying to getActivity().
http.newCall(request).enqueue(new Callback(...
onResponse(Call call, Response response) {
...
getActivity().runOnUiThread(...) // <-- getActivity() was null when it had been destroyed already
IMO the solution is to prevent callbacks to occur when the fragment is no longer alive anymore (and that's not just with Okhttp).
The fix: Prevention.
If you have a look at the fragment lifecycle (more info here), you'll notice that there's onAttach(Context context) and onDetach() methods. These get called after the Fragment belongs to an activity and just before stop being so respectively.
That means that we can prevent that callback to happen by controlling it in the onDetach method.
#Override
public void onAttach(Context context) {
super.onAttach(context);
// Initialize HTTP we're going to use later.
http = new OkHttpClient.Builder().build();
}
#Override
public void onDetach() {
super.onDetach();
// We don't want to receive any more information about the current HTTP calls after this point.
// With Okhttp we can simply cancel the on-going ones (credits to https://github.com/square/okhttp/issues/2205#issuecomment-169363942).
for (Call call : http.dispatcher().queuedCalls()) {
call.cancel();
}
for (Call call : http.dispatcher().runningCalls()) {
call.cancel();
}
}
Where do you call this function? If you call it in the constructor of Fragment, it will return null.
Just call getActivity() when the method onCreateView() is executed.
Do as follows. I think it will be helpful to you.
private boolean isVisibleToUser = false;
private boolean isExecutedOnce = false;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_my, container, false);
if (isVisibleToUser && !isExecutedOnce) {
executeWithActivity(getActivity());
}
return root;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;
if (isVisibleToUser && getActivity()!=null) {
isExecutedOnce =true;
executeWithActivity(getActivity());
}
}
private void executeWithActivity(Activity activity){
//Do what you have to do when page is loaded with activity
}
Those who still have the problem with onAttach(Activity activity), Its just changed to Context -
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
In most cases saving the context will be enough for you - for example if you want to do getResources() you can do it straight from the context. If you still need to make the context into your Activity do so -
#Override
public void onAttach(Context context) {
super.onAttach(context);
mActivity a; //Your activity class - will probably be a global var.
if (context instanceof mActivity){
a=(mActivity) context;
}
}
As suggested by user1868713.
Another good solution would be using Android's LiveData with MVVM architecture.
You would define a LiveData object inside your ViewModel and observe it in your fragment, and when LiveData value is changed, it would notify your observer (fragment in this case) only if your fragment is in active state, so it would be guaranteed that you would make your UI works and access the activity only when your fragment is in active state. This is one advantage that comes with LiveData
Of course when this question was first asked, there was no LiveData. I am leaving this answer here because as I see, there is still this problem and it could be helpful to someone.
Call getActivity() method inside the onActivityCreated()
I have solved my problem this way.I have passed getApplicationContext from the previous class which has already access of getApplicationContext.I have passed Inputstream object to my new class Nutrients.
try{
InputStream is= getApplicationContext().getAssets().open("nutrient_list.json");
Nutrients nutrients=Nutrients.getNutrients(topRecognition,is);
} catch (IOException e) {
e.printStackTrace();
}
Write a common method that will ensure you will never get null Activity.
public class BaseFragment extends Fragment {
private Context contextNullSafe;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
/*View creation related to this fragment is finished here. So in case if contextNullSafe is null
* then we can populate it here.In some discussion in - https://stackoverflow.com/questions/6215239/getactivity-returns-null-in-fragment-function
* and https://stackoverflow.com/questions/47987649/why-getcontext-in-fragment-sometimes-returns-null,
* there are some recommendations to call getContext() or getActivity() after onCreateView() and
* onViewCreated() is called after the onCreateView() call every time */
if (contextNullSafe == null) getContextNullSafety();
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
contextNullSafe = context;
}
/**CALL THIS IF YOU NEED CONTEXT*/
public Context getContextNullSafety() {
if (getContext() != null) return getContext();
if (getActivity() != null) return getActivity();
if (contextNullSafe != null) return contextNullSafe;
if (getView() != null && getView().getContext() != null) return getView().getContext();
if (requireContext() != null) return requireContext();
if (requireActivity() != null) return requireActivity();
if (requireView() != null && requireView().getContext() != null)
return requireView().getContext();
return null;
}
/**CALL THIS IF YOU NEED ACTIVITY*/
public FragmentActivity getActivityNullSafety() {
if (getContextNullSafety() != null && getContextNullSafety() instanceof FragmentActivity) {
/*It is observed that if context it not null then it will be
* the related host/container activity always*/
return (FragmentActivity) getContextNullSafety();
}
return null;
}

Categories

Resources