Nicolas400
Nicolas400

Reputation: 653

How to fill spinner with data from room, with MVVM architecture

I want to know the best practice/way to fill any Spinner with data from room db.

I also want to use ViewModel and LiveData (then I'll move to StateFlow!), but I'm confused with the correct order defining variables.

first I have this in the view model:

val aniosLiveData = anioRepository.anios.asLiveData() // return  LiveData<List<Anio>>

then on the fragment, first the viewmodel declaration:

private val ensayosViewModel: EnsayosViewModel by viewModels()

then, in onViewCreated() I have a block with the binding elements:

 binding.apply {
        recyclerViewEnsayos.apply {
            adapter = ensayosAdapter
            layoutManager = LinearLayoutManager( requireContext())
            setHasFixedSize(true)
        }
        spinnerAnio.apply {
            adapter = aniosAdapter  // <- Spinner adapter
        }
    }

I override onCreate() to define an observer, and then I put this lines:

       ensayosViewModel.aniosLiveData.observe(viewLifecycleOwner, {spinnerData ->
        aniosAdapter = ArrayAdapter<Anio>(requireContext(), R.layout.spinner_text_item, spinnerData)
    })

Where/When do I need to declare "aniosAdapter" ? like this: ?

 //At class level
 private lateinit var aniosAdapter : ArrayAdapter<Anio>

Is this the correct way ? There is another ?? more simpler ?

Thanks in advance! Best Regards

Upvotes: 0

Views: 443

Answers (1)

buggily
buggily

Reputation: 418

If you need reference to the aniosAdapter outside of the lifecycle hook, I would recommend using a private lateinit var as you alluded. While you are initializing the spinnerAnio's adapter correctly at first, it's not going retroactively recognize any mutations you make to aniosAdapter after the execution of the lifecycle hook. Instead, you're going to need to adjust your aniosLiveData observer to appear as such:

ensayosViewModel.aniosLiveData.observe(viewLifecycleOwner, {
    binding.spinnerAnio.adapter = ArrayAdapter<Anio>(
        requireContext(),
        R.layout.spinner_text_item,
        it
    )
})

In the scenario where you do need to reference the aniosAdapter outside of the lifecycle hook's scope, your observer would likely look as such in conjunction with the private lateinit var you referenced:

ensayosViewModel.aniosLiveData.observe(viewLifecycleOwner, {
    aniosAdapter = ArrayAdapter(
        requireContext(),
        R.layout.spinner_text_item,
        it
    )

    binding.spinnerAnio.adapter = aniosAdapter
})

If you can guarantee that your observer will trigger immidately, aniosAdapter would be safe to declare as a private lateinit var. If you are unsure, it would be much safer to consider it as an optional field as depicted below. Nice work!

private var aniosAdapter: ArrayAdapter<Anio>? = null

Upvotes: 1

Related Questions