What is the best place to call getContext()? - android

I was reading fragment documentation and found this:
Caution: If you need a Context object within your Fragment, you can call getContext(). However, be careful to call getContext() only when the fragment is attached to an activity. When the fragment isn't attached yet or was detached during the end of its lifecycle, getContext() returns null
So my question is what is the best place to call getContext() inside the fragment. Like i can call it in onCreateView, or onCreate() or onAttach() on any other place.
I am asking this because recently I got a crash of null pointer using getContext in my fragment. So I thought I should create a global Context object and access it inside the fragment. But then I came across this text from official documentation so I am a bit confused what would be the best place to initialize this Context object.

It all depends what you need that Context for. Sometimes it's just fine to call getApplicationContext(), in other cases it may be needed to use what you are given in onAttach() or call getActivity() if you are in Fragment code. Some are also providing own Application subclass, exposing static method like getAppContext().
In any case, AVOID saving the context as it may lead to memory leak. Get it dynamically when needed only.

As a lot of wrong answers are given, I'll provide what's the best way to handle context inside fragments.
The best solution is checking if the context has a value whenever you need it.
You can do it by wrapping the code in which you access the fragment in 2 ways:
if (getContext() != null) { /* code here */ }
or, as stated in the documentation there's this method:
isAdded()
which: "Return true if the fragment is currently added to its activity." -reference
Again: please AVOID saving the context in a local fragment's variable.

You can do something like this in your fragment.
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
// After this point the context is initialized.
context=activity;
}
NOTE: I don't really get it why it is so not liked this answer.
First af all, depending on the version of android(which was not mentioned), of course the OnAttach is deprecated, it has to be checked.
Next:
I think that if you need cobntext somewhere, you can make a private or protected variable in Fragment, so the context is destroyed when it is garbage collected.
protected MainActivity activity;
Make sure you hold this variable dearly and its reference is not passed to other classes.
This should do the job.

You can implement your logic like this :
private Context mContext;
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public void onDetach() {
mContext = null;
super.onDetach();
}
When you required to use context,
if(mContext != null) {
//Add your logic here
}

Related

Difference between getContext() and requireContext() when using fragments

I've been having this doubt since a long time, when I'm working with android fragments and I need to instantiate a Context, or I need to pass a Context as argument for other function, I can choose to use between getContext() and requireContext() methods to achieve that, I normally prefer to use requireContext(), but just because the IDE(Android Studio) shows warnings sometimes when I use the getContext().But the result of using one or other method seems to be the same, no matter what I choose.
My question is, is there any difference between these two methods? If this is the case, which one is better, or which should I use in each case?
getContext() returns a nullable Context.
requireContext() returns a nonnull Context, or throws an exception when one isn't available.
If your code is in a lifecycle phase where you know your fragment is attached to a context, just use requireContext() to get a Context and also keep static analyzers happy about potential NPE issues.
If your code is outside of regular fragment lifecycle (say, an async callback), you might be better off using getContext(), checking its return value yourself and only proceeding using it if it was non-null.
Being explicit with nullability is even more important in Kotlin where it is built into the language's type system.
While Laalto's answer is correct, I'm adding the code to prove the difference between requireContext() and getContext.
In Fragment.java you should see the following code.
#NonNull
public final Context requireContext() {
Context context = getContext();
if (context == null) {
throw new IllegalStateException("Fragment " + this + " not attached to a context.");
}
return context;
}
You can see that the requireContext() method throws an exception when the context is null.
#Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
On the other hand, If you see the code for getContext(), there is a chance that you might get a null value when called.

Get parent activity in DialogFragment subclass before show()

I am working on an android application with many dialogs, all of which extend a custom class called "DialogFragmentBase" which extends the library's "DialogFragment". All activities use the show() method overridden in DialogFragmentBase.
I want to prevent showing the dialogs if the parent activity is backgrounded (as in receiving a phone call) since that results in the illegalStatEexception, but at the same time I don't want to guard every show() call in the application with:
if(getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED))
So I wanted to do something like this in the DialogFragmentBase:
#Override
public void show(FragmentManager manager, String tag){
List<Fragment> fragments = manager.getFragments();
if(fragments != null && fragments.size() > 0){
FragmentActivity activity = fragments.get(fragments.size()-1).getActivity();
if(activity != null && activity.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)){
super.show(manager, tag);
}
}
}
So my question is: Is accessing the previous fragment like that considered a bad practice? It does work...but I remember reading somewhere that fragments shouldn't intercommunicate. If it is indeed a bad practice, what would be a better solution that can be implemented in the DialogFragmentBase (to avoid adding guards everywhere).
Note: I tried the onSaveInstanceState solution described here, but since the DialogFragment hasn't been shown yet, the onSaveInstanceState isn't called for it at that point. Also getActivity() returns null since onAttach hasn't been called yet at that point.
Thanks!
The support library FragmentManager has an isStateSaved() method. Depending on exactly what your requirements are, you could leverage this to check if it is "safe" to show your dialogs:
#Override
public void show(FragmentManager manager, String tag) {
if (!manager.isStateSaved()) {
super.show(manager, tag);
}
}
Note that the above implementation is relatively similar to using commitAllowingStateLoss(), in that you'll silently fail to show your dialog in certain cases. But perhaps that is fine for your requirements.
Perhaps you could create a new method in your dialog base class:
public void showIfResumed(FragmentActivity activity, String tag) {
if (/* your check here, e.g. activity.getLifecycle()... */) {
show(activity.getSupportFragmentManager(), tag);
}
}
And then, in your activities, rather than calling show(getSupportFragmentManager(), TAG), you could call showIfResumed(this, TAG). You'll still have to change every call to show() to a call to showIfResumed(), but this would reduce the code duplication considerably.

How can I get a view from a Context in Android?

in my project I am passing a context of an activity to a helper class. Now, is it possible to use that context and find the views from that activity? Basically, I would like to find the views by id, but just using a context object.
How can I achieve this?
Provided you stored your context in a private reference, do this (MonoDroid)
View parent = ((Activity)_context).Window.DecorView.FindViewById(Android.Resource.Id.Content);
In Raw Android it'd look something like:
View parent = ((Activity)mContext).getWindow().getDecorView().findViewById(android.R.id.content)
Activity is a Context, so if you actually pass your Activity to a helper class, you can just:
void someMethodInHelperClass(Context c) {
if(c instanceof Activity) {
((Activity)c).findViewById(R.id.someviewid);
}
}
Of course it will be much easier if you change your method to:
void someMethodInHelperClass(Activity c) {

Need to instantiate an Android activity to pass to another method

I am trying to call this method:
public static void trackFunXStartActivity(Activity a)
{
s.startFunXActivity(a);
}
I'm trying to call it using this code in my LayoutsActivity.java:
public void onStart() {
TrackFunX.trackFunXStartActivity(LayoutsActivity);
}
but I'm not sure how to create or reference the Activity that I can pass to trackFunXStartActivity(Activity a). I don't think I can pass LayoutsActivity as an Activity.
How do I go about instantiating or reference an activity in LayoutsActivity.java to pass to trackFunXStartActivity.
I'm a Android newbie and have done some searches on StackOverflow but didn't see anything to help with this questions.
Thanks
take a static context for the LayoutsActivity like
static Context context;
and in the oncreate method use
context = LayoutsActivity.this
and finally you can use this context in the class where you need

What is the correct way to implement a constructor in android, application context in particular?

What is the correct way to implement a constructor in android?
It seems that in an Activity or Service 'onCreate()' is where the magic happens.
The reason I ask is because I would like to be sure I'm doing the right thing declaring
attributes in the top of my classes (Context in particular) and then setting the attribute values inside onCreate.
// Activity launched via an Intent, with some 'extras'
public class SomeActivity extends Activity {
private Context context;
private String foo;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the object attribute for later use, good or Bad to do this?
context = getApplicationContext();
Intent fooIntent = getIntent();
foo = fooIntent.getStringExtra("foo");
}
private void someMethodThatNeedsContext() {
// For example:
Cursor c = this.context.getContentResolver().query(foo, xxx, xxx);
// Or is it better practice to:
// A) Pass the context as a local variable to this method
// B) Use getApplicationContext() locally when needed
}
}
Maybe either of these options is ok, and I'm over thinking it?
Any specific reading and/or suggestions you may have would greatly be helpful to me.
Yes, you are correct that initialization is supposed to take place in onCreate(). You don't really need neither to store a reference to a context, nor to call getApplicationContext(). Your activity is a context itself, so you just use wherever you need a context. For example, making a toast within an activity:
Toast.makeToast(this, "Some text", Toast.LENGTH_LONG).show();
Option B - Since you can call getApplicationContext() from any non-static methods in your Activity class.
In fact, Activity is derived from Context too (Somewhere in the inheritance tree..) so you can just do:
Cursor c = getContentResolver()....
You don't have to keep a reference to a context. Especially not static, that can cause problems.
And you are correct - since you usually don't create your own constructor for Activities, you put the code for construction in onCreate.
You are writing a method inside your activity, so you can call getApplicationContext() anywhere in your code, you don't need to use a local variable :
Cursor c = getApplicationContext().getContentResolver().query(foo, xxx, xxx);
Also remember that the activity itself is a context (the Activity class is derived from Context), so generally you can use this whenever you need to provide a context ( for example when creating an Intent : new Intent(this, ...)).

Categories

Resources