Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

viewModelFactory variable has not been initialized when utilizing fragments

Now, this error is showing when I try to run my app in my device

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property viewModelFactory has not been initialized

This project is using fragments, unlike the previous project when the above worked.

class MainFragment : Fragment() {
    private lateinit var binding: FragmentMainBinding
    private lateinit var adapter: MainAdapter
    private lateinit var viewModel: MainViewModel
    @Inject lateinit var viewModelFactory: MainViewModelFactory
    ...
    private fun populateUi() {
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(MainViewModel::class.java)
        ...
    }
}

MainViewModelFactory:

class MainViewModelFactory @Inject constructor(private val mainViewModel: MainViewModel) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            return mainViewModel as T
        }

        throw IllegalArgumentException("Unknown class name")
    }
}

I also have this module:

@Module
class ViewModelModule {
    @Provides
    @Singleton
    fun provideMainViewModel(factory: MainViewModelFactory): ViewModelProvider.Factory = factory
}

being used in my AppComponent:

@Singleton
@Component(modules = [
    AndroidInjectionModule::class,
    BuilderModule::class,
    AppModule::class,
    NetworkModule::class,
    DaoModule::class,
    ViewModelModule::class
])
interface AppComponent {
    fun inject(app: App)
}

And this module that uses @ContributeAndroidInjector for activity and fragments

@Module
abstract class BuilderModule {
    @ContributesAndroidInjector
    abstract fun contributeMainActivity(): MainActivity

    @ContributesAndroidInjector
    abstract fun contributeMainFragment(): MainFragment
}

The root of the app, which previously had only the activity injection:

class App : Application(), HasActivityInjector, HasSupportFragmentInjector {
    @Inject
    lateinit var activityInjector: DispatchingAndroidInjector<Activity>

    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent
            .builder()
            .appModule(AppModule(this))
            .networkModule(NetworkModule("https://jsonplaceholder.typicode.com/"))
            .build()
            .inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity> {
        return activityInjector
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment> {
        return fragmentInjector
    }
}

The previous app I built did not make use of fragments, and I still think it could be this the reason it fails in this project that does use fragments.


1 Answers

I solved this by adding

override fun onAttach(context: Context?) {
    super.onAttach(context)
    AndroidSupportInjection.inject(this)
}

But I'd like to do as the same in the activity. Why doesn't it work as well, using the BuilderModule?


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!