Problem to get Context in FragmentView Kotlin - android

I need to get a Context from my activity. When i do that using:
override fun getContext(): Context {
return activity.applicationContext
}
i got:
safe ( .) or non-null asserted ( .) calls are allowed on a nullable receiver of type FragmentACtivity

For formality purposes, posting answer here
activity is calling your fragment's getActivity() which isn't guaranteed to not be null. So you'll have to do activity!!.applicationContext!!
There are scenarios in the life cycle of Android where the activity will be null during the instance of your Fragment. More often than not, activity will exist, but in this case Kotlin is forcing you to be smart about accessing it. A simple (but helpful) nuance of Kotlin

Related

When should we call getContext and getActivity once and for all?

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 :).

Fragment: Avoiding getActivity() to return null by overriding OnActivityCreated?

I must call getActivity in my fragment. I have read on Stackoverflow e.g. that we could store the activity in a class/object attribute, but I have read that it's a bad practice too.
Would it be possible to override onActivityCreated in the fragment, and simply execute all my logic (which requires getActivity) in this callback?
It should avoid any NullException.
I would say use a WeakReference to your activity, you can use it to access the activities members from a fragment
https://developer.android.com/reference/java/lang/ref/WeakReference

Should we always nullcheck Context inside a fragment?

I have a very simple on click listener in my fragment:
button?.setOnClickListener {
val intent = Intent(MyActivity.createIntent(context!!)) // crash here because context is null
startActivity(intent)
}
Crashlytics shows that some users are getting KotlinNullPointerException crashes when clicking on this specific button. Now I know the problem is happening because I am force unwrapping the Context. If I simply wrapped it inside a nullcheck, it would not crash.
But I assume that there's a bigger underlying issue in my code because I always force unwrap context when I need it and I only have issues with this specific piece of code.
What's the rule here? Should we always nullcheck our Context or not?
If you will look at the source code of fragment.getContext() method, you will see:
#Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
Which means that getContext can return null. Internally mHost represents an Activity fragment is attached to. Fragment isn't always attached to it's hosting activity, you can observe this using onAttach / onDetach lifecycle callbacks.
In your case, as already mentioned, best approach would be to use context from a View
view.setOnClickListener { it.context }
But in general, always check nullable things, and don't do !! even if you're sure it is not null. In such way you will have less error prone code, providing an alternative way of handling nulls.
Inside button click you can easily use : view.getContext() to get the context or in Kotlin
it.context // which will be never null
i.e,
button?.setOnClickListener {
val intent = Intent(MyActivity.createIntent(it.context)) // this wont ever crash
startActivity(intent)
}
most propably you will be okay with code like that
button?.setOnClickListener {startActivity(MyActivity.createIntent(it.context))}
I believe on your MyActivity.createIntent() fun you return Intent

Bad idea to override getContext() to non-null in Android api level 27?

I'm using kotlin, and recently updated my application with compileSdkVersion/targetSdkVersion 27. There I get some compilation errors, where for instance, context is now nullable(context?) instead of non-null.
I have a base fragment class, that other fragments inherits from. Is it a bad idea to have this function?
override fun getContext(): Context {
return super.getContext()!!
}
In the parent function, I see that you have this code:
/**
* Return the {#link Context} this fragment is currently associated with.
*/
#Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
Where mHost is:
// Host this fragment is attached to.
FragmentHostCallback mHost;
But the fragment will always be attached to a host, as far as I can see.
Is there any kind of scenario where mHost will be null?
Edit: In support library v27.1.0 Fragments now have requireContext(), requireActivity(), requireHost(), and requireFragmentManager() methods, which return a NonNull object of the equivalent get methods or throw an IllegalStateException.
See https://developer.android.com/reference/android/support/v4/app/Fragment.html#requireContext()
There can be situations where the fragment is not attached to a host. The simplest example is when the fragment is instantiated with its empty constructor and is not attached to anything. If you called getContext() in the constructor (or a method called from the constructor), it would result in a null value.
This means that overriding getContext() to return super.getContext() would make no sense. You might be able get rid of some null-checks but if it's null, your app will crash.
Reason being there are cases where fragments won't be attached to the parent yet but you try to access it,in such case context will be null.Best example is when you have tabs with multiple fragments and you keep switching between the tabs, most possible case is fragments will be detached and take time to attach it back but you have already switched to other tabs resulting your app to crash. So keeping context nullable is one of the best practice.

Android context from tab activity

I have a helper class that I need context so I can access the SharedPrefences. Other posts recommend passing in the application context on instantiation of the helper class. So I made that change, it works very well except within a tab activity. The tab activity need to call a webservice to determine what data to display. The helper class makes the webservice call.
You can call getContext() from any activity. If the helper class is defined as a subclass of the activity, it can call it directly. Otherwise, passing the context through instantiation would be my second choice. I agree, it's not pretty passing contexts everywhere. There are probably some complicated OOP patterns you could use to avoid this, but I can't see it being an advantage overall.
If you get a null pointer you might be calling the function too early. In what function are you calling it?

Categories

Resources