Search code examples
androidfirebaseandroid-architecture-components

Android: Firebase ViewModel Architecture


I have viewModel class, firebase class, and a fragment.

In the fragment I'm observing microbes list from viewModel:

        viewModel = ViewModelProvider(this).get(ViewModelMicrobes::class.java)
    viewModel.microbes.observe(viewLifecycleOwner, Observer { microbes ->
        var microbesList = mutableListOf<Microbe>()
        for(microbeMap in microbes){
            val microbe = Microbe(microbeMap["name"] as String)
            microbesList.add(microbe)
        }
        adapter.microbes = microbesList
    })

    viewModel.fetchMicrobes(this)

In the viewModel class I'm fetching microbes from the firebase class:

    fun fetchMicrobes(owner: ViewModelStoreOwner){
    val firebase = FirebaseMicrobes()
    firebase.fetchMicrobes(owner)
}

fun setMicrobes(microbeMaps: List<Map<String, Any>>){
    _microbes.value = microbeMaps
}

In the firebase class I'm fetching microbes and calling setMicrobes from the viewModel:

    fun fetchMicrobes(owner: ViewModelStoreOwner){
    val database = Firebase.database
    val microbesRef = database.getReference("microbes")
    microbesRef.addValueEventListener(object: ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            val children = snapshot.children
            val viewModel = ViewModelProvider(owner).get(ViewModelMicrobes::class.java)
            var microbes = mutableListOf<HashMap<String, Any>>()
             for(child in children){
                 microbes.add(child.value as HashMap<String, Any>)
             }
            viewModel.setMicrobes(microbes)
        }

        override fun onCancelled(p0: DatabaseError) {

        }
    })
}

Is that a correct way to do it? I need to create a viewModel instance in the firebase class, so I'm passing "this" in the fragment when calling the viewModel's method, so then the viewModel's method can pass the owner to firebase class, so the firebase class can create viewModel instance.


Solution

  • Passing owner would not be a good option, instead you should define a livedata in ypur firebase class, while fetching data from viewmodel' fetchMicrobe() start observing Livedata passed from Firebase class, when response is received, post data to livedata, and as you are already observing this livedata in viewmodel class, set here your list. Thus without passing your owner you will be able to fetch data, Your code will be decoupled, will follow best practices and will be helpful in testing your code.