我尝试学习如何使用 Dagger 2。请帮助解决以下异常:
异常:UninitializedPropertyAccessException:lateinit 属性行程尚未初始化
主要活动视图模型:
class MainActivityViewModel : ViewModel() {
private lateinit var tripsLiveData: MutableLiveData<List<Trip>>
@Inject
lateinit var trips : List<Trip>
fun getTrips() : LiveData<List<Trip>> {
if (!::tripsLiveData.isInitialized){
tripsLiveData = MutableLiveData()
tripsLiveData.value = trips
}
return tripsLiveData
}
}
Run Code Online (Sandbox Code Playgroud)
行程模块:
@Module
class TripModule{
@Provides
fun provideTrips(): List<Trip> {
var list = ArrayList<Trip>()
list.add(Trip(100,10))
list.add(Trip(200,20))
return list
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序组件:
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBuilder::class,
TripModule::class])
interface AppComponent{
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: MyApplication)
}
Run Code Online (Sandbox Code Playgroud)
主要活动:
class MainActivity : AppCompatActivity() {
@Inject
lateinit var tripsAdapter: TripsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
// Inject external dependencies
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupRecyclerView();
setUpViewModel();
}
private fun setupRecyclerView() {
recycler_view.apply {
layoutManager = LinearLayoutManager(context)
adapter = tripsAdapter
}
}
private fun setUpViewModel(){
val model = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
model.getTrips().observe(this, Observer { tripsAdapter.trips = it!! })
}
}
Run Code Online (Sandbox Code Playgroud)
如果您希望视图模型成为匕首图的一部分,则需要做几件事 - 使用匕首的多重绑定(只需一次,对于较新的视图模型会更容易)。您将创建新的视图模型工厂,它将负责实例化视图模型。该工厂将成为 dagger graph 的一部分,因此将引用通过 dagger 提供的任何内容。然后,您可以通过视图模型主体@Inject constructor(anyParameterFromDagger: Param)或@Inject lateinit var someParam: Param在视图模型主体内部进行构造函数注入。
1) 为视图模型类创建限定符
\n\n@MustBeDocumented\n@Target(AnnotationTarget.FUNCTION)\n@Retention(AnnotationRetention.RUNTIME)\n@MapKey\nannotation class ViewModelKey(val value: KClass<out ViewModel>)\nRun Code Online (Sandbox Code Playgroud)\n\n2)创建视图模型工厂,它从 dagger 的多重绑定中获取值
\n\n@Singleton\nclass DaggerViewModelFactory @Inject constructor(\n private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>\n) : ViewModelProvider.Factory {\n\n @Suppress("UNCHECKED_CAST")\n override fun <T : ViewModel> create(modelClass: Class<T>): T {\n var creator: Provider<out ViewModel>? = creators[modelClass]\n if (creator == null) {\n for ((key, value) in creators) {\n if (modelClass.isAssignableFrom(key)) {\n creator = value\n break\n }\n }\n }\n if (creator == null) {\n throw IllegalArgumentException("unknown model class $modelClass")\n }\n try {\n return creator.get() as T\n } catch (e: Exception) {\n throw RuntimeException(e)\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n3)有匕首模块,它将提供工厂(从第2点开始),然后是你的视图模型
\n\nabstract class YourDaggerModuleWhichThenNeedToBePartOfYourGraphAsIncluded {\n\n @Binds\n abstract fun bindViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory // this needs to be only one for whole app (therefore marked as `@Singleton`)\n\n @Binds\n @IntoMap\n @ViewModelKey(MainActivityViewModel::class)\n abstract fun bindMainActivityViewModel(vm: MainActivityViewModel): ViewModel // for every viewmodel you have in your app, you need to bind them to dagger\n}\nRun Code Online (Sandbox Code Playgroud)\n\n4)在您的活动中,当您获取视图模型时,您需要使用 dagger 中的工厂:(更改的地方在// TODO下面的代码中标记为 \xc2\xa0)
class MainActivity : AppCompatActivity() {\n\n @Inject\n lateinit var tripsAdapter: TripsAdapter\n\n @Inject\n lateinit var viewModelFactory: ViewModelProvider.Factory // TODO this was added to the activity\n\n override fun onCreate(savedInstanceState: Bundle?) {\n\n // Inject external dependencies\n AndroidInjection.inject(this)\n\n super.onCreate(savedInstanceState)\n setContentView(R.layout.activity_main)\n\n setupRecyclerView();\n setUpViewModel();\n }\n\n private fun setupRecyclerView() {\n recycler_view.apply {\n layoutManager = LinearLayoutManager(context)\n adapter = tripsAdapter\n }\n }\n\n private fun setUpViewModel(){\n val model = ViewModelProviders.of(this, viewModelFactory)[MainActivityViewModel::class.java] // TODO this was changed\n\n model.getTrips().observe(this, Observer { tripsAdapter.trips = it!! })\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我没有提供将模块包含到 dagger 组件的代码,因为我希望这是您已经做过的事情。
\n\n您可以在这篇中等文章中阅读更多相关信息(我不是该文章的作者):
\n