I have a Fragment with a constructor that takes multiple arguments. My app worked fine during development, but in production my users sometimes see this crash:
android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment
make sure class name exists, is public, and has an empty constructor that is public
I could make an empty constructor as this error message suggests, but that doesn’t make sense to me since then I would have to call a separate method to finish setting up the Fragment.
I’m curious as to why this crash only happens occasionally. Maybe I’m using the ViewPager incorrectly? I instantiate all the Fragments myself and save them in a list inside the Activity. I don’t use FragmentManager transactions, since the ViewPager examples I have seen did not require it and everything seemed to be working during development.
Yes they do.
You shouldn’t really be overriding the constructor anyway. You should have a
newInstance()static method defined and pass any parameters via arguments (bundle)For example:
And of course grabbing the args this way:
Then you would instantiate from your fragment manager like so:
This way if detached and re-attached the object state can be stored through the arguments. Much like bundles attached to Intents.
Reason – Extra reading
I thought I would explain why for people wondering why.
If you check: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Fragment.java
You will see the
instantiate(..)method in theFragmentclass calls thenewInstancemethod:http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#newInstance() Explains why, upon instantiation it checks that the accessor is
publicand that that class loader allows access to it.It’s a pretty nasty method all in all, but it allows the
FragmentMangerto kill and recreateFragmentswith states. (The Android subsystem does similar things withActivities).Example Class
I get asked a lot about calling
newInstance. Do not confuse this with the class method. This whole class example should show the usage.