我正在尝试将ViewModelFactory注入到我的Activity中,但它仍然抛出同样的错误:lateinit属性viewModelFactory尚未初始化。我找不到我可能做错的事。从我的课程中查看上面的代码
AppComponent.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
}
MainModule.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)
}
MainActivity.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()
})
}
}
TweetSentimentsApplication.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()
}
}
答案 0 :(得分:12)
当您初始化inject(mainActivity: MainActivity)
时,您必须调用AppComponent
中定义的MainActivity
方法,这就是Dagger实际注入您需要的依赖项的方法。
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)
...
}
答案 1 :(得分:3)
此外,请确保将您的应用程序名称添加到 AndroidManifest.xml 文件中。
<application
android:name=".YourAppName"
..../>
答案 2 :(得分:1)
您也可以这样做:
@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 :(得分:1)
您也可以扩展 DaggerAppCompatActivity 代替 AppCompatActivity 。例如
class MainActivity : DaggerAppCompatActivity() {
@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()
})
}
}
答案 4 :(得分:0)
您也可以这样做:
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
val mainViewModel: MainViewModel by lazy {
ViewModelProviders.of(this, viewModelFactory)[MainViewModel::class.java]
}
答案 5 :(得分:0)
我的错误是创建一个新对象并从中获取一个组件,例如App().component
。
因此,在这种情况下,您需要将component字段放在companion object
中,并用App.component
替换代码
答案 6 :(得分:0)
也许您错过了在片段/活动中实现“可注入”接口。将片段/活动标记为可注射。