代码之家  ›  专栏  ›  技术社区  ›  Guilherme Lima Pereira

Dagger2+Kotlin:Lateinit属性尚未初始化

  •  10
  • Guilherme Lima Pereira  · 技术社区  · 6 年前

    我正试图将ViewModelFactory注入到我的活动中,但它始终引发相同的错误:LateInit属性ViewModelFactory尚未初始化。我找不到我可能做错了什么。从我的课上看到上面的代码

    应用组件.kt

    @Component(modules = [(AppModule::class), (NetworkModule::class), (MainModule::class)])
    interface AppComponent {
    
        fun inject(application: TweetSentimentsApplication)
    
        fun inject(mainActivity: MainActivity)
    
        fun context(): Context
    
        fun retrofit(): Retrofit
    }
    

    主模块.kt

    @Module
    class MainModule {
    
        @Provides
        fun mainViewModelFactorty(repository: TweetRepository): MainViewModelFactory = MainViewModelFactory(repository)
    
        @Provides
        fun local(database: AppDatabase): TweetLocal = TweetLocal(database)
    
        @Provides
        fun remote(tweetService: TweetService): TweetRemote = TweetRemote(tweetService)
    
        @Provides
        fun tweetService(retrofit: Retrofit): TweetService = retrofit.create(TweetService::class.java)
    
        @Provides
        fun repository(local: TweetLocal, remote: TweetRemote): TweetRepository = TweetRepository(local, remote)
    
    }
    

    主活动.kt

    class MainActivity : AppCompatActivity() {
    
        @Inject lateinit var viewModelFactory: MainViewModelFactory
    
        private val viewModel: MainViewModel? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.main_activity)
    
            ViewModelProviders.of(this, viewModelFactory).get(MainViewModel::class.java)
    
            viewModel?.init("guuilp")
            viewModel?.getTweetList()?.observe(this, Observer {
                Toast.makeText(this, it?.size.toString(), Toast.LENGTH_LONG).show()
            })
        }
    }
    

    tweet情感应用.kt

    open class TweetSentimentsApplication: Application(){
    
        companion object {
            lateinit var appComponent: AppComponent
        }
    
        override fun onCreate() {
            super.onCreate()
    
            initDI()
        }
    
        private fun initDI() {
            appComponent = DaggerAppComponent.builder()
                    .appModule(AppModule(this))
                    .build()
        }
    }
    
    3 回复  |  直到 6 年前
        1
  •  13
  •   zsmb13    6 年前

    你必须打电话给 inject(mainActivity: MainActivity) 您在中定义的方法 AppComponent 当您初始化 MainActivity 这就是匕首如何注入你需要的依赖性。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
    
        // This is where the dependencies are injected
        TweetSentimentsApplication.appComponent.inject(this)
    
        ViewModelProviders.of(this, viewModelFactory).get(MainViewModel::class.java)
    
        ...
    }
    
        2
  •  2
  •   Droid Teahouse    6 年前

    您也可以这样做:

      @Inject
      lateinit var viewModelFactory: ViewModelProvider.Factory
      val mainViewModel: MainViewModel by lazy {
          ViewModelProviders.of(this, viewModelFactory)[MainViewModel::class.java]
      }
    

    并将抽象模块与@contributesandroidinjector一起用于活动,以及 视图模型的抽象模块。使用抽象更有效:

       @Module
       abstract class AndroidBindingModule {
    
       @ContributesAndroidInjector
        internal abstract fun contributesAnActivity(): AnActivity
        }
    
    
    
     @Module
        abstract class ViewModelModule {
          //the default factory only works with default constructor
          @Binds
          @IntoMap
          @ViewModelKey(AViewModel::class)
          abstract fun bindArtViewModel(aViewModel: AViewModel): ViewModel
    
          @Binds
          abstract fun bindViewModelFactory(factory: AViewModelFactory): ViewModelProvider.Factory
        }
    
    
    
    
    
     @Documented
        @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
        @Retention(RetentionPolicy.RUNTIME)
        @MapKey
        internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
    
        3
  •  0
  •   Droid Teahouse    6 年前

    您也可以这样做:

      @Inject
      lateinit var viewModelFactory: ViewModelProvider.Factory
      val mainViewModel: MainViewModel by lazy {
          ViewModelProviders.of(this, viewModelFactory)[MainViewModel::class.java]
      }