Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

To use Koin to achieve the use of the same fragment type in a viewpager but with different instances of viewmodel in each tab, with varying parameters, you can follow these steps:

  1. Define a ViewModelFactory class that takes parameters in its constructor.
class MyViewModelFactory(private val param1: String, private val param2: Int) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return modelClass.getConstructor(String::class.java, Int::class.java)
            .newInstance(param1, param2)
    }
}
  1. Define a Koin module for each ViewModel instance that you want to create.
val myModule = module {
    factory { (param1: String, param2: Int) -> MyViewModelFactory(param1, param2) }
    factory { (param1: String, param2: Int) -> MyViewModel(param1, param2) }
}
  1. In your Fragment, inject the ViewModelFactory and ViewModel instances for each tab.
class MyFragment : Fragment() {
    private val viewModelFactory by inject<(String, Int) -> ViewModelProvider.Factory>()
    private lateinit var viewModel: MyViewModel

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val position = arguments?.getInt("position") ?: 0
        val param1 = "param1 for tab $position"
        val param2 = position
        viewModel = ViewModelProvider(this, viewModelFactory(param1, param2)).get(MyViewModel::class.java)
    }
}
  1. Finally, when creating your viewPager adapter, pass in the arguments for each tab and use the same Fragment type.
class MyViewPagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
    override fun getItem(position: Int): Fragment {
        val args = Bundle()
        args.putInt("position", position)
        val fragment = MyFragment()
        fragment.arguments = args
        return fragment
    }
    override fun getCount(): Int {
        return 3
    }
}

With this approach, you can reuse the same MyFragment instance in each tab of the ViewPager but with different instances of MyViewModel, each with varying parameters.