Inject ViewModel using Dagger 2 + Kotlin + ViewModel

后端 未结 6 1390
-上瘾入骨i
-上瘾入骨i 2021-02-07 07:07
class SlideshowViewModel : ViewModel() {

@Inject lateinit var mediaItemRepository : MediaItemRepository

fun init() {
    What goes here?
}

So I\'m tr

6条回答
  •  悲哀的现实
    2021-02-07 07:54

    Refer to a repo I created when I was learning dagger+kotlin

    Essentially you need a ViewModelFactory instance to the UI layer, you use that to create a viewmodel.

    @AppScope
    class ViewModelFactory
    @Inject
    constructor(private val creators: Map, @JvmSuppressWildcards Provider>)
        : ViewModelProvider.Factory {
    
    
        @SuppressWarnings("Unchecked")
        override fun  create(modelClass: Class): T {
            var creator = creators[modelClass]
    
            if (creator == null) {
                for (entry in creators) {
                    if (modelClass.isAssignableFrom(entry.key)) {
                        creator = entry.value
                        break
                    }
                }
            }
    
            if (creator == null) throw IllegalArgumentException("Unknown model class" + modelClass)
    
            try {
                return creator.get() as T
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
    

    Your ViewModelModule should look like (this is where you store all viewmodels).

    @Module
    abstract class ViewModelModule {
        @AppScope
        @Binds
        @IntoMap
        @ViewModelKey(YourViewModel::class)
        abstract fun bindsYourViewModel(yourViewModel: YourViewModel): ViewModel
    
        // Factory
        @AppScope
        @Binds abstract fun bindViewModelFactory(vmFactory: ViewModelFactory): ViewModelProvider.Factory
    }
    

    Then create a dagger map key

    @Documented
    @Target(AnnotationTarget.FUNCTION)
    @Retention(AnnotationRetention.RUNTIME)
    @MapKey
    internal annotation class ViewModelKey(val value: KClass)
    

    Then on your UI layer, inject the factory and instantiate your viewmodel using ViewModelProviders

    class YourActivity : BaseActivity() {
        @Inject
        lateinit var viewModelFactory: ViewModelProvider.Factory
    
        lateinit var yourViewModel: YourViewModel
    
        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            ...
            (application as App).component.inject(this)
        }
    
        override fun onStart() {
            super.onStart()
            yourViewModel = ViewModelProviders.of(this, viewModelFactory).get(YourViewModel::class.java)
    
            // you can now use your viewmodels properties and methods
            yourViewModel.methodName() 
            yourViewModel.list.observe(this, { ... })
    
        }
    

提交回复
热议问题