In Android, we can use Singleton
pattern to store data that we require across multiple activities during the whole app lifecycle. This is considered a memory leak and has its cons, but practically speaking, this approach is used widely (at least in Android programming).
Coming to the main point, in Navigation Component, we follow a single activity pattern which remains available throughout the app lifecycle. Also, this documentation says that a shared activity-level ViewModel
can be used to share data between different fragments. I think this is a fairly reasonable way to share data between multiple fragments but I still want to validate this approach before going ahead and using it with Navigation Component
. My question is whether we should use an activity-level ViewModel
to store small amounts of data that I need throughout the app lifecycle in a Navigation Component
based application (remember I only have a single activity)? Also, what implications/pros/cons this approach can have over the Singleton-based approach?
If you're planning to move to a single activity architecture for your app, you can surely share data by using the same view model across fragments. To do so you can use a Kotlin property delegate from the fragment-ktx
artifact.
Let's say you like to share the same data between a master and a detail fragment, the only thing you'll need to do is to declare two view model instances in the two fragment that have the same activity scope:
class MasterFragment : Fragment() {
// Use the 'by activityViewModels()' Kotlin property delegate
// from the fragment-ktx artifact
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.state.observe(viewLifecycleOwner, {
// do something with your state
})
}
}
class DetailFragment : Fragment() {
// same scope of your MasterFragment
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.state.observe(viewLifecycleOwner, {
// do something with your state
})
}
}
Pros:
In addition, the use of a singleton pattern is suggested for "application level" entities, such a database or a hardware resource, I would definitely not recommend to use a singleton for something so related to the UI like a view model class.