Multiple instances of same fragment type with different ViewModel type based on argument passed to fragment

Viewed 482

I have application with ViewPager2. All pages in it are instances of same type fragmet. All pages are displaying some lists in a recyclerview, of different data types. Data are populated from some API endpoint, using Retrofit calls.

I'm using dagger 2 to inject viewmodels.

Everything is working fine with one page. Now I want to create other pages, and I'm asking is there any method/pattern to implements other pages without creating different fragment classes, but only to use different viewModel type?

Maybe some generic viewModel or something.

1 Answers

PageType

enum class PageType {
    Page1, Page2, Page3;
}

val PageType.viewModelClass: KClass<out GenericViewModel>
    get() = when (this) {
        PageType.Page1 -> Page1ViewModel::class
        // todo
    }

ViewModel

abstract class GenericViewModel<T>() : BaseViewModel() {

    abstract val pageType: PageType
}

class Page1ViewModel @Inject constructor() : GenericViewModel() {
    override val pageType: PageType = PageType.Page1
}

Fragment

class PageFragment : BaseFragment() {

    private val pageType: PageType by lazy {
        TODO("read from arguments bundle")
    }

    private val vm: GenericViewModel by lazy {
        ViewModelProvider(this, viewModelFactory).get(pageType.viewModelClass.java)
    }

    companion object {
        fun newInstance(type: PageType): PageFragment {
            TODO("add type into bundle and set as arguments")
        }
    }
}

If your current dagger setup works for viewmodels, then you won't have to do anything special to support this pattern.

Related