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?
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.
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!
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With