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