Android create ViewModel with parameters without dagger

This post will go through the steps and code for creating ViewModel that contains parameters without using a dependency injection framework such as dagger hilt.

Here is a ViewModel which needs a parameter in order to instantiate it.

class MyViewModel(
    private val messageDataStore: MessageDataStore,
): ViewModel() { ... }

Here is factory class for instantiating ViewModels, ViewModelFactory.kt

/**
 * Factory for all ViewModels.
 */
@Suppress("UNCHECKED_CAST")
class ViewModelFactory constructor(
    private val messageDataStore: MessageDataStore,
    owner: SavedStateRegistryOwner,
    defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
    override fun  create(
        key: String,
        modelClass: Class,
        handle: SavedStateHandle
    ) = with(modelClass) {
        when {
            isAssignableFrom(MyViewModel::class.java) ->
                MyViewModel(messageDataStore)
            else ->
                throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
        }
    } as T
}

Here is the application class with the required parameter for instantiating the ViewModel. In this case, it’s a custom data store instance MessageDataStore.

class MyApp : Application() {
    val messageDataStore: MessageDataStore
        get() = MessageDataStore.getInstance(this)

}

Here is a file with extension functions for getting the ViewModelFactory in Activity and Fragment. ViewModelUtilExt.kt

fun AppCompatActivity.getViewModelFactory(savedInstanceState: Bundle?): ViewModelFactory {
    val messageDataStore = (applicationContext as MyApp).messageDataStore
    return ViewModelFactory(messageDataStore, this, savedInstanceState)
}

fun Fragment.getViewModelFactory(savedInstanceState: Bundle?): ViewModelFactory {
    val messageDataStore = (requireContext().applicationContext as MyApp).messageDataStore
    return ViewModelFactory(messageDataStore, this.requireActivity(), savedInstanceState)
}

Getting the ViewModel in Activity.

class MainActivity : AppCompatActivity() {

  private lateinit var myViewModel: MyViewModel
  // Other code...

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val vm by viewModels { getViewModelFactory(savedInstanceState) }
    myViewModel = vm
    // Other code...
  }
}

Getting the ViewModel in Fragment.

class MyFragment : Fragment() {
    private lateinit var myViewModel: MyViewModel
    //Other code...

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
      val vm by activityViewModels { getViewModelFactory(savedInstanceState) }
      myViewModel = vm
      //Other code...
  }
}

Search within Codexpedia

Custom Search

Search the entire web

Custom Search