Home > OS >  How to share viewmodel between two fragments which belong to two different activities
How to share viewmodel between two fragments which belong to two different activities

Time:09-17

I am trying to understand how can I use my same viewmodel across different fragments which even belongs to different activities.

So let's say I have Activity1 with Fragment A, Fragment B and Activity2 with Fragment C. How do I create a single instance of viewmodel that I can use across all these fragments.

I tried understanding shared viewmodel but seems like it is to be used if sharing data between fragments of a single activity and not multiple activities.

So basically I want to create a single instance of viewmodel across all the fragments? How can I achieve this functionality also keeping in mind the MVVM approach.

Any help would be appreciated. Thanks!

CodePudding user response:

This is not supported. Google's recommendation is to put all your screens in a single Activity.

But, you can make an intermediate singleton class that each instance of the ViewModel uses.

Or maybe you could use a factory that treats it like a temporary singleton and does reference counting so it doesn't get cleared too early or hang onto the reference for too long. Untested example of what I mean:

private var viewModelInstance: MyViewModel? = null
private var refCount = 0

class MyViewModel: ViewModel() {

    override fun onCleared() {
        if (--refCount > 0) {
            return
        }
        viewModelInstance = null
        
        // Do typical onCleared cleanup here
    }
}

class MyViewModelFactory: ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        require(modelClass.isAssignableFrom(MyViewModel::class.java)) { "Factory only supports MyViewModel" }
        refCount  
        viewModelInstance = viewModelInstance ?: MyViewModel()
        return viewModelInstance as T
    }
}

CodePudding user response:

Shared viewmodel between multiple activities is not supported.

One way to achieve this using AndroidViewModel. You can create a ViewModel extending AndroidViewModel . This requires application instance. This viewmodel will be binded to application lifecycle and same instance will be available through out the lifecycle of the application. In one activity you can add data, and in other activity you can get updated data. This will be acting something like singleton instance(But not exactly).

Addition to this, you can also use live data in AndroidViewModel if you use observer with activity/fragment lifecycle owner. So the observer will be live only till life cycle of fragment or activity.

ViewModel:

   class AppViewModel constructor(private val mApplication: Application) :
        AndroidViewModel(mApplication) {
     //ViewModel Logic
    }

Initializing Viewmodel: You can initialize viewmodel like this in any fragment or activity.

val appViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(MyApp.getInstance())
            .create(AppViewModel::class.java)

Application Class:

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
    mInstance = this
}

    companion object {    
        lateinit var mInstance: CooperApp

        @Synchronized
        fun getInstance(): MyApp {
            return mInstance
        }
    }
}

Also one more thing we can use is like initializing viewmodel in application class and create similar function to getInstance() which will return viewmodel instance and use it all over the app

  • Related