evant / kotlin-inject

Dependency injection lib for kotlin
Apache License 2.0
1.14k stars 51 forks source link

Fragment requires an empty constructor #382

Closed M-Miyazako closed 2 months ago

M-Miyazako commented 2 months ago

The Android documentation describes how to inject the ViewModel. https://github.com/evant/kotlin-inject/blob/main/docs/android.md#viewmodels

@Inject
class HomeViewModel(private val repository: HomeRepository) : ViewModel()

@Inject
class HomeFragment(homeViewModel: () -> HomeViewModel) : Fragment() {
    private val viewModel by viewModels {
        viewModelFactory { addInitializer(HomeViewModel::class) { homeViewModel() } }
    }
}

But, as stated in the official reference, Fragment must have an empty constructor or an exception may be raised.

https://developer.android.com/reference/android/app/Fragment.html

All subclasses of Fragment must include a public no-argument constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the no-argument constructor is not available, a runtime exception will occur in some cases during state restore.

And the problem did indeed occur. The app crashes when switching the device to dark mode or using the split screen feature. Is there a way around this problem?

M-Miyazako commented 2 months ago

I had overlooked it!

When you set FragmentFactory, you need to do it before super.onCreate.

class MainActivity : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.fragmentFactory =
            MainActivityComponent::class.create(ApplicationComponent.getInstance(this))
                .fragmentFactory
        super.onCreate(savedInstanceState)
    }
}

I had reversed the order, which caused the problem. After I fixed it, the app no longer crashes.

I hope this helps anyone else with the same problem.

evant commented 2 months ago

Also note that you linked to the deprecated platform Fragment, If you look at the [androidx documentation](https://developer.android.com/reference/androidx/fragment/app/Fragment#Fragment()) it does point you to FragmentFactory.

evant commented 2 months ago

And sorry I'm going to go ahead and close this, it may be useful but it's not really related to kotlin-inject directly.