MVVM architecture with custom view
Asked Answered
B

3

13

I want to make a custom view in android with MVVM architecture. First of all, I want to ask, is ViewModel working perfectly with a custom view as it works in case of activity or fragment? Can we get ViewModel from ViewModel provider in a custom view?

If I need to make a separate custom view what will the correct approach?

Bekki answered 4/9, 2019 at 14:9 Comment(1)
The Architecture Components ViewModels are made to work with Activities and Fragments, not with the lifecycle of a View, but if you want you can check these articles: 1. medium.com/@matthias.c.siegmund/… 2. medium.com/@polson55/…Whorehouse
E
8

Q: Can we get ViewModel from ViewModel provider in a custom view?

Ans: Simple answer would be yes you can !

But How? (Further explanation) ViewModelProviders required either context as Activity or Fragment. So you can retrieve context from your CustomView class using getContext() which would be Activity/Fragment where you're using it.

Cast that context to either of type & provide it to ViewModelProviders which will give you object of that Activity/Fragment container.

Hence using like this, you can share ViewModel between your CustomView and Activity/Fragment.


Side Note: You can also make your CustomView implement LifeCycleObserver, in such way you can also make your view respect lifecycle of Activity/Fragment for initialization/destruction stuffs.

Eugenides answered 6/9, 2019 at 9:24 Comment(2)
ViewModelProviders.of(context) no longer exists in the newest version. How do I do this using the replacement (ViewModelProvider() that takes a LifecycleOwner)?Biomass
Yes, that's tricky now. To consume it via context you'll need to cast it to LifecycleOwner for ViewModelProvider. And on custom view, getting context will always be of Activity you're inflating to.Eugenides
K
14

A better alternative would be to use the new API view.findViewTreeViewModelStoreOwner() which gives you the viewModelStoreOwner(Fragment if view is attached to the fragment o/w activity)

You can create ViewModelProvider and then get the ViewModel.

Below is an example of code in Kotlin

private val viewModel by lazy(LazyThreadSafetyMode.NONE) {
        ViewModelProvider(viewModelStoreOwner).get(ViewModel::class.java)
}

Similarly, there are other similar APIs like view.findViewTreeLifecycleOwner() and view.findViewTreeSavedStateRegistryOwner()

It is a much cleaner approach as you don't have to typecast your context into Activity or Fragment and will scale to other implementations of ViewModelStoreOwner as well.

One thing to note here is that view may have a shorter life span compared to Activity/Fragment and so you might have to make a custom view Lifecycle(so that your LiveData subscription gets managed properly) using LifecycleRegistry based on onAttachedToWindow and onDetachedFromWindow callbacks

Kingofarms answered 18/9, 2021 at 20:56 Comment(1)
Note that these methods are only available after onAttachToWindow().Gorden
E
8

Q: Can we get ViewModel from ViewModel provider in a custom view?

Ans: Simple answer would be yes you can !

But How? (Further explanation) ViewModelProviders required either context as Activity or Fragment. So you can retrieve context from your CustomView class using getContext() which would be Activity/Fragment where you're using it.

Cast that context to either of type & provide it to ViewModelProviders which will give you object of that Activity/Fragment container.

Hence using like this, you can share ViewModel between your CustomView and Activity/Fragment.


Side Note: You can also make your CustomView implement LifeCycleObserver, in such way you can also make your view respect lifecycle of Activity/Fragment for initialization/destruction stuffs.

Eugenides answered 6/9, 2019 at 9:24 Comment(2)
ViewModelProviders.of(context) no longer exists in the newest version. How do I do this using the replacement (ViewModelProvider() that takes a LifecycleOwner)?Biomass
Yes, that's tricky now. To consume it via context you'll need to cast it to LifecycleOwner for ViewModelProvider. And on custom view, getting context will always be of Activity you're inflating to.Eugenides
I
-1
CustomView: ViewModelStoreOwner{

  private var viewModel: YourViewModel

  override fun getViewModelStore() = ViewModelStore() 

  init{
    viewModel = ViewModelProvider(this)[YourViewModel::class.java]
  }

}

In summary, this code defines a custom view (CustomView) in an Android app that implements the ViewModelStoreOwner interface. It creates and manages a YourViewModel instance using a ViewModelProvider, ensuring that the ViewModel survives configuration changes and is associated with the CustomView's lifecycle. The getViewModelStore() function provides a ViewModelStore to manage the ViewModel instances. This pattern is commonly used in Android app development to separate and manage UI-related data and logic.

Ison answered 13/3, 2023 at 13:22 Comment(2)
Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, can you edit your answer to include an explanation of what you're doing and why you believe it is the best approach?Scarlett
Fairly sure this is just chat gpt gibberish...Coben

© 2022 - 2024 — McMap. All rights reserved.