I'm trying to implement Dragger 2 in recyclerview but I'm getting following error when running the app:
kotlin.UninitializedPropertyAccessException: lateinit property apiComponent has not been initialized
at com.kabelash.squarerepos.MyRetroApplication$Companion.getApiComponent(MyRetroApplication.kt:18)
at com.kabelash.squarerepos.network.viewmodel.RetroViewModelFactory.create(RetroViewModelFactory.kt:21)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at com.kabelash.squarerepos.network.view.RetroFragment.initViewModel(RetroFragment.kt:43)
at com.kabelash.squarerepos.network.view.RetroFragment.onCreate(RetroFragment.kt:29)
APIComponent.kt
@Singleton
@Component(modules = [AppModule::class, APIModule::class])
interface APIComponent {
fun inject(retrofitRepository: RetrofitRepository)
fun inject(retroViewModel: RetroViewModel)
fun inject(retroFragment: RetroFragment)
fun inject(retroViewModelFactory: RetroViewModelFactory)
}
NetworkActivity.kt class NetworkActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.network_layout)
replaceFragment()
}
fun replaceFragment(){
supportFragmentManager
.beginTransaction()
.replace(R.id.container_retro_room, RetroFragment())
.commit()
}
}
RetroFragment.kt
class RetroFragment: Fragment() {
lateinit var retroViewModel: RetroViewModel
var fragmentView:View?=null
private var listAdapter: PostListAdapter?=null
private var postListLayoutBinding:PostListLayoutBinding?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initViewModel()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
postListLayoutBinding = DataBindingUtil.inflate(inflater, R.layout.post_list_layout,container,false)
fragmentView = postListLayoutBinding?.root
initAdapter()
setAdapter()
fetchRetroInfo()
return fragmentView
}
fun initViewModel(){
var retroViewModelFactory = RetroViewModelFactory()
retroViewModel = ViewModelProviders.of(this,retroViewModelFactory).get(RetroViewModel::class.java)
}
fun fetchRetroInfo(){
retroViewModel.postInfoLiveData?.observe(this,object:Observer<List<PostInfo>>{
override fun onChanged(t: List<PostInfo>?) {
t?.apply {
listAdapter?.setAdapterList(t)
}
}
})
}
private fun setAdapter(){
fragmentView?.post_list?.apply {
layoutManager = LinearLayoutManager(activity)
addItemDecoration(DividerItemDecoration(activity, DividerItemDecoration.VERTICAL))
adapter = listAdapter
}
}
private fun initAdapter(){
listAdapter = PostListAdapter(this@RetroFragment.requireActivity())
}
}
RetroViewModelFactory.kt class RetroViewModelFactory : ViewModelProvider.Factory { lateinit var apiComponent: APIComponent @Inject lateinit var retrofitRepository: RetrofitRepository
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
// initDaggerComponent()
var apiComponent : APIComponent = MyRetroApplication.apiComponent
apiComponent.inject(this)
if (modelClass.isAssignableFrom(RetroViewModel::class.java)) {
return RetroViewModel(retrofitRepository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
fun initDaggerComponent(){
apiComponent = DaggerAPIComponent
.builder()
.aPIModule(APIModule(APIURL.BASE_URL))
.build()
apiComponent.inject(this)
}
}
Can someone help to fix this issue? I couldn't figure it out.
As the exception message says, you have a property called apiComponent
marked with lateinit
in your MyRetroApplication
class, which has not been initialized. A lateinit
property causes this exception if you attempt to read its value (such as here, within the factory) before setting it. You should create an instance of APIComponent
in the MyRetroApplication
class when your application starts, and assign it to that property.