Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject viewmodel in a customView with koin?

I know how to inject viewmodel in Activities or Fragments with koin:

private val regionSelectorViewModel: RegionSelectorViewModel by viewModel()

Right now I am setting viewmodel to my customView like this:

fun setViewModel(viewModel: RegionSelectorViewModel) {
    mViewModel = viewModel
}

The viewmodel is initialized in Activity and passed through parameter to view. But... I would like to inject viewmodels in customViews as I do in the activities or fragments. Is there a way to do that using koin?

like image 764
Ángel Gómez García Avatar asked Apr 07 '20 10:04

Ángel Gómez García


People also ask

How do you use viewModels?

There are three steps to setting up and using a ViewModel: Separate out your data from your UI controller by creating a class that extends ViewModel. Set up communications between your ViewModel and your UI controller. Use your ViewModel in your UI controller.

How do you inject ViewModel in KOIN?

To inject a ViewModel in an Activity , Fragment or Service use: by viewModel() - lazy delegate property to inject a ViewModel into a property. getViewModel() - directly get the ViewModel instance.


1 Answers

In the end I got a solution for this problem, we only have to get viewmodel from activity context:

  private val viewModel: VersionViewModel by lazy {
    (context as FragmentActivity).getViewModel()
  }

Another solution, or for me the best solution is create a delegate to get viewmodel from a view.

inline fun <reified T : ViewModel> ViewGroup.viewModel(): ReadOnlyProperty<ViewGroup, T> =
  object : ReadOnlyProperty<ViewGroup, T> {

    private var viewModel: T? = null

    override operator fun getValue(
      thisRef: ViewGroup,
      property: KProperty<*>
    ): T = viewModel ?: createViewModel(thisRef).also { viewModel = it }

    private fun createViewModel(thisRef: ViewGroup): T {
      return (thisRef.context as FragmentActivity).getViewModel()
    }
  }


class CustomView @JvmOverloads constructor(
  context: Context,
  attrs: AttributeSet? = null,
  defStyleAttr: Int = 0,
  defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {

  private val viewModel: CustomViewModel by viewModel()
  
}
like image 169
Ángel Gómez García Avatar answered Oct 18 '22 00:10

Ángel Gómez García