I have a dialog fragment that displays an image whose bytecode is passed to the constructor.
When the dialog is appeared and I am in dark mode and try to change the mode to light one and I come back to my screen, the screen appears all white and I get the error below :
Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment *.*.*.PictureLoaderDialogFragment: could not find Fragment constructor
I instantiate my fragment dialog as below:
class PictureLoaderDialogFragment(
private var bitmapByteArray: ByteArray?
) : DialogFragment(){
companion object {
@JvmStatic
fun newInstance(
bitmapByteArray: ByteArray? = null
) = PictureLoaderDialogFragment(bitmapByteArray)
}
}
Any idea how it should be fixed ?
This error is caused by passing an argument to your fragment's constructor.
This has to do with the life cycle of fragments and their interaction with the activity. Fragments in Android are designed to be reusable and can be created and destroyed at different points in time depending on the activity's lifecycle. When creating fragments, the Android system uses an empty constructor with no arguments to create a new instance of the fragment after the device configuration changes (in this case, the device theme changes).
In order to solve this problem, there are 3 solutions:
Bundle
FragmentFactory
Dependency Injection
(DI)Since you used the newInstance
method in your code, the following example shows how to use it, following the first way and saving arguments in a Bundle
:
class PictureLoaderDialogFragment : DialogFragment() {
//...
companion object {
fun newInstance(bitmapByteArray: ByteArray? = null): PictureLoaderDialogFragment {
val fragment = PictureLoaderDialogFragment()
val args = Bundle()
args.putByteArray("bitmap", bitmapByteArray)
fragment.arguments = args
return fragment
}
}
}
You can access the passed arguments inside the PictureLoaderDialogFragment
:
val bitmapByteArray = arguments?.getByteArray("bitmap")
bitmapByteArray?.let {
val image = BitmapFactory.decodeByteArray(it, 0, it.size)
imageView.setImageBitmap(image)
}
You can show your DialogFragment
:
PictureLoaderDialogFragment.newInstance(bitmapByteArray).show(manager, tag)
This article explains how you can use FragmentFactory
by following the second solution way
The third way to solve — here, you can learn how to use dependency injection using Hilt