How to access a function from a viewModel in another viewModel

Viewed 1318

I have 2 viewModels -

  1. MainViewModel**
  2. StorageViewModel

StorageViewModel.kt

class StorageViewModel @ViewModelInject constructor(private val preferenceStorage: 
 PreferenceStorage, @ApplicationContext context: Context) : ViewModel() {

   ........
   //save last played song
   fun saveLastPlayedSong(song: Songs){
    viewModelScope.launch {
        protoDataStoreManager.saveLastPlayedSong(song)
     }
    }

  }

Now, I want to call the saveLastPlayedSong function in MainViewModel

MainViewModel.kt

class MainViewModel @ViewModelInject constructor(
private val musicServiceConnection: MusicServiceConnection,
private val storageViewModel: StorageViewModel
) : ViewModel(){ 

 .........
 
fun playOrToggleSong(
    mediaItem: Songs, toggle: Boolean = false
)
{
    //here, I want to call the function from StorageViewModel e.g 
    storageViewModel.saveLastPlayedSong(mediaItem)  
  }
}

How do I instantiate the "StorageViewModel" inside MainViewModel and whats the best way (Good Practice).

I'm using MVVM and Hilt.

1 Answers

This is usually a symptom of bad architecture.

If StorageViewModel is acting like a Repository it should not extend ViewModel. If it doesn't have connections to UI you can convert it to a repository class and that would solve your problem because it would just become an injectable singleton.

If StorageViewModel is connected to a Fragment (for example) you should take a reference to both viewmodels and pass data between them from the UI layer.

Something like:

class StorageFragment : Fragment {
  private val storageViewModel: StorageViewModel by viewModels()
  private val mainActivityViewModel: MainViewModel by activityViewModels()

  //....

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    //you can do this if the song saving is a UI related thing
    //just have playOrToggleSong accept a function as parameter
    //as success callback
    button.setOnClickListener {
      mainActivityViewModel.playOrToggleSong(...) {
        storageViewModel.saveLastPlayedSong(param)
      }
    }
  }
}
Related