Is calling the method getActivity() once in my fragment and saving the reference in mActivity better than calling getActivity() every time I want to show a toast message?
Toast.makeText(mActivity, text, duration).show();
vs.
Toast.makeText(getActivity(), text, duration).show();
getActivity() should be preferred for 2 reasons:
1) Memory leak prevention
Having a variable mActivity lying around opens up opportunities for memory leak e.g. mistakenly set the variable as static, makes it easy and convenient to reference the activity in some running anonymous AysncTask
2) Correct nature of fragment-activity relationship
Fragments can be attached or detached at many point of times. Therefore, getting a reference of the activity hosting the current fragment should be on a on-demand basis. Having a mActivity variable means you need to set and unset it correctly.
Take note that what Toast requires here is a Context object so it's not necessarily the activity that is required here. An application context object would also suffice
Fragment wise both are same
First one
Activity mActivity = getActivity();
#Override
public void onClick(View arg0) {
Toast.makeText(**mActivity**,"Text!",Toast.LENGTH_SHORT).show();
}
Second one
use Directly like this
Toast.makeText(getActivity(),"Text!",Toast.LENGTH_SHORT).show();
if you just need a Context or Activity, no difference. but if you want to access some method or field inside the parent activity, you would better saving the reference in mActivity.
If you want the context just to show the Toast messages and getting references to Activity is difficult for you then you can use getApplicationContext() instead.
Related
I searched a lot on StackOverflow and more generally on Google for explanations about the use of contexts in the Android environment, but I only found scattered fragments of explanations.
When should we use getContext instead of getActivity? The question is precised below.
Within a DialogFragment, and other Fragment: creating a Toast, building an AlertDialog,instanciating an Intent... require a context. Should we use getActivity or getContext?
And if these operations are written in an Activity instead of a fragment?
By the way, a Null exception and/or memory leaks can occur by calling getContext and getActivity: when? More precisely: does it occur only when the lifetime of the caller is a (strict) subset of the lifetime of the called object (for example, a Dialog calls getActivity/getContext which returns null if it's not yet attached to its activity)?
From the DOCS, The Context object contains global information about an application environment. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
the getContext() method returns the context associated with the current object, which may be a View, or a Fragment or Dialog or any other object that has this method defined in it or inherits it.
the getActivity() method returns a reference to the current activity associated with a Fragment object. If there is no activity associated with the fragment it WILL return null. I personally never use this method when passing a context argument, I only use getContext() and getApplicationContext().
getApplicationContext() is especially useful because it uses a Context whose lifecycle is separate from the current context, it is tied to the lifetime of the process rather than the current component. Which means it uses the context of the App instead of that of part of the app, like an activity. see here
Context Best Practices:
getContext() and getApplicationContext() are sufficient for passing a context argument. If they are not accessible immediately you can use getActivity().getApplicationContext() chaining to pass appropriate context argument. This means you can use this to create Toasts, AlertDialogs, Intents, Fragments and other view manipulations that require context.
Never assign a context to a static (class) variable, It will create a memory leak!
If you use getApplicationContext() to register broadcasts you must perform the appropriate clean-up to prevent memory leaks. see here
Note that these are my personal approaches, I stand to be corrected :).
I have an Activity with some Fragments. From each fragment, I need to call aMethod() implemented by the Activity. So, I do something like this:
((MyActivity)getActivity()).aMethod();
I'm referencing the activity many times, so I decided hold a reference to the activity. When fragment is created, I have:
MyActivity act; // this s a fragment's member
//...
act = (MyActivity) getActivity();
I'm wondering if holding that reference could result in a memory leak.
If so, I have thought in two solutions:
act = null; when fragment is destroyed (onDestroy())
Using a WeakReference: act = new WeakReference((MyActivity) getActivity());
Are both valid? Does it make sense?
You don't even need to hold a reference. Just keep using
getActivity()
A fragment lifecycle is joined to that of its activity so you don't need to worry about it.
If you still want to store a reference, a safe bet is to use the WeakReference as you said yourself.
This will make the reference available for garbage collection when needed. Just keep checks for not null before using the reference though.
Nope that's not memory leak.
We are getting instance of Activity from where we can load fragment.
so you also need to pass instance of Activity or As per you already do casting and through getActivity() is correct.
But Remember one thing whenever onPause(), onStop() and onDestroy() called at that time to release instace of Activity otherwise it holds memory and Garbage collector not clear it so in such senario/situations only memory leak occurs.
I need to show some dialogs as debug in my app.
The structure of the app itself is written so that it is easier to actually call and show the dialog from a static class with static methods. These methods all points toward a bigger method which eventually take care of the requests.
What I'd like to achieve is to call an eventual Dialog (I'm using the Material Dialog library by afollestad on github) which needs a reference to the current activity.
I actually have a private static Activity sActivity; field in the class, and the relative setActivity(Activity activity) method.
Currently, I've got my own CustomApplication from which I call this:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
MyStaticClass.setActivity(activity);
}
[...]
}
which is not working as intended because this
try {
Utils.showSimpleDialog(sActivity, "Error", message);
} catch (MaterialDialog.DialogException d) {
d.printStackTrace();
}
is always calling the catch case.
My question is, is it possible to avoid the setActivity call from every single Activity? If yes, how? Thank in advance!
It's not a good idea to keep a static reference to an Activity as it can cause memory leaks with leaked contexts.
Edit to answer if it would still be dangerous if setting static activity to null in onDestroy as previously asked in a comment under this answer
Setting to null in onDestroy doesn't always serve as a workaround to this because if you run out of memory you can get into a state where Android can actually stop at the onPause stage of the lifecycle and not even hit onDestroy. Keeping static contexts is generally to be avoided.
It looks like showSimpleDialog already takes an Activity parameter. When you are calling it from an Activity, simply pass this , or from a fragment, pass getActivity(). If this call to showSimpleDialog is called from another utility method you've implemented, just pass an activity to that method also rather than setting a static Activity on the class.
As mentioned here:
"be careful to call getActivity() only when the fragment is attached to an activity. When the fragment is not yet attached, or was detached during the end of its lifecycle, getActivity() will return null."
I have a couple of questions regarding calling getActivity() inside DialogFragment.
What are different scenarios under which a DialogFragment can unexpectedly get detached from its parent Activity or didn't attach at the first place? The thing is I am calling getActivity() inside onPositiveButtonClick's listener and have received a couple of crash reports (Null pointer exception) for it. I am unable to reproduce the crash, screen orientation doesn't seem to do the trick.
What are some recommended guidelines on how to use getActivity() with minimal damage? I have read some other stackoverflow posts which suggest
a) Override onAttach() method.
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
I would prefer this less as it keeps an instance of the Activity. Also, how can I be sure local instance of the activity is never set to null. Would like to know the pros and cons before using it.
b) Will delegating the onClick() implementations to the calling activity using an interface help? If yes, how?
If all of this is unavoidable, I don't see a better alternative than letting the app crash. I can't show a toast since getActivity() is null and would avoid letting the onClick operation fail silently.
Any pointers would be much appreciated. Thank you!
I tend to call getActivity().getApplicationContext() a lot in my fragments, would it be a bad idea to just to set a Context field variable by default on my fragments? We are starting android development at work and I don't want to create any bad habits for the group.
Its not recommended to use getApplicationContext() , just use the Activity context , also in some conditions getActivity() might return null in Fragments, so i think getting Activity Context on onAttach(Activity activity) is a better way in Fragments.
I don't see a reason to use the Application Context while you could use directly the Activity instance.
Please notice that if the fragment is detached from the activity the getActivity() will return you Null as a result. So you have to see the application logic.
If the fragment needs to do something even after it is detached from the activity then keep the activity as a field, otherwise simply check if (getActivity() != null)
One reason where I have seen it useful to store the application context as a field in a fragment is when the fragment is of the type that don't have any UI and it's purpose is to start a task that does something in the background, and the fragment also have the setRetainInstance(true); to be kept on rotation.
In that case the activity can be recreated on rotation but the task that do the background thing in the background can continue and is held by the fragment. Let's say the result of that task have fetched something from Internet and then want to store it in a database, then the callback for the task comes back to the fragment. A call to getActivity()could result in null due to a potential rotation, the application context is however kept so therefore a field with the application context is handy because it is not destroyed when the activity is. The getActivity().getApplicationContext() would need to be called in the onAttach() method and stored to a field.