Reputation: 848
I am using navigation architecture component library and my app's starting point is this fragment:
class MainFragment : BaseFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
Which inherits from an abstract class which is BaseFragment
:
abstract class BaseFragment : Fragment() {
}
When I run my app I get:
Unable to instantiate fragment io.example.MainFragment: calling Fragment constructor caused an exception
But this does not happen if MainFragment
extends Fragment
instead of BaseFragment
. What is the reason? Does this have something to do with how the Navigation Architecture Component works?
Upvotes: 20
Views: 11213
Reputation: 1348
If you're getting this error
androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment calling Fragment constructor caused an exception
While using Geofencing API in Fragments, it's because you're not meant to initialize GeofencingClient (or perhaps it could be some other variable on your end) before the Fragment gets constructed, so, delay the initialization of GeofencingClient with a lateinit var
and then initialize it in onCreateView.
Upvotes: 0
Reputation: 51
I faced similar issues for a while now. In order to fix the issue, do not use a context related resource before context is initialized.
For example, in case you are using getString()
method (context related resource) to access a string value, do use it always in the onViewCreated()
method of fragment.
This ensures the context is initialized and thus can be access.
Hope this helps!
Upvotes: 3
Reputation: 161
I had the same error and none of the above answers helped me because it was actually a different mistake I had made.
class RunFragment : Fragment() {
private lateinit var runViewModel: RunViewModel
var calories= String.format("%.2f",runViewModel.calories)
var distanceTravelled= String.format("%.2f",runViewModel.distanceTravelled)
var stepsRun= String.format("%.2f",runViewModel.stepsRun)
}
before onCreateView
my runViewModelhad not yet been instantiated since it was lateinit but I was already referring to it. Changing it to this below solved the problem
private lateinit var runViewModel: RunViewModel
var calories= ""
var distanceTravelled= ""
var stepsRun= ""
override fun onCreateView(.......): View? {
calories= String.format("%.2f",runViewModel.calories)
distanceTravelled= String.format("%.2f",runViewModel.distanceTravelled)
stepsRun= String.format("%.2f",runViewModel.stepsRun)
}
Upvotes: 2
Reputation: 186
I had the same issue, but only on older Android versions. It turned out I had to use a direct descendant of Fragment()
Couldn't tell you why this was an issue as it ran fine on newer versions, but I had no choice but to refactor... painful but now functional.
Upvotes: 0
Reputation: 7098
I had the similar issue because I had val in MyBaseFragment
protected abstract val gpsMsg: String
which I was overiding this way in other Fragment before fragment attached to context.
override val gpsMsg: String = getString(R.string.gps_not_enabled)
So the underlying error was because context was null and getString uses getResources()
which returns requireContext().getResources()
. And in the requireContext()
source code error will be thrown.
public final Context requireContext() {
Context context = getContext();
if (context == null) {
throw new IllegalStateException("Fragment " + this + " not attached to a context.");
}
return context;
}
So the error thrown causes fragment not to be instantiated. So I would advice being careful with context thing when override.
Upvotes: 18