Reusing Fragments/Bottomsheets with viewModel as data binding variable

Viewed 487

I will give an example so as to easily explain my problem.

Consider FragmentA with ViewModelA and FragmentB with ViewModelB being used in my app.

I have a BottomSheetSample that is to be used in both FragmentA and FragmentB Since the bottom sheet is doing very little, like selecting a value I want to share the ViewModel of the fragment on which the bottom sheet is being displayed on, instead of having a separate ViewModel and transferring the data to the ViewModel of the fragment. I am binding the ViewModel like this to the nav graph.

Inside FragmentA

private val viewModel: ViewModelA by navGraphViewModels(R.id.nav_A_graph) { viewModelFactory }

Inside BottomSheetSample

private val viewModel: ViewModelA by navGraphViewModels(R.id.nav_A_graph) { viewModelFactory }

I am passing the ViewModel to the XML like this so as to use it with data-binding:

val binding: BottomSheetSampleBinding =
            DataBindingUtil.inflate(inflater, R.layout.bottomSheet, container, false)
binding.viewModel = viewModel

sample bottom sheet XML:

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>

        <variable
            name="viewModel"
            type="com.ui.fragmenta.ViewModelA" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->viewModel.oneSelected()} />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->viewModel.twoSelected()} />
    </LinearLayout>
</layout>

Now the issue is that I have to use the same Bottom Sheet(BottomSheetSample) in FragmentB also. Since I am passing the ViewModel to the XML for data binding, I am not able to use the same bottom sheet as the current BottomSheetSampleBinding is expecting an object of ViewModelA.

So what I end up doing is creating a new BottomSheetSampleB which does exactly the same thing as BottomSheetSample and just change the ViewModel in the new XML to ViewModelB :

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>

        <variable
            name="viewModel"
            type="com.ui.fragmentb.ViewModelB" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->viewModel.oneSelected()} />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->viewModel.twoSelected()} />
    </LinearLayout>
</layout>

Now if I have to use the same BottomSheet in a third fragment I have to copy the BottomSheetSample and do the whole thing again. This looks redundant as the same bottom sheet is being replicated again and again. But I don't know how to avoid doing this. Can someone tell me the right way to do this?

Hopefully, I am clear about my issue.

1 Answers

Create a BaseViewModel (Any name) and keep all the things required for bottom sheet in BaseViewModel . Use this BaseViewModel in Bottom Sheet

<layout>

    <data>

        <variable
            name="viewModel"
            type="com.ui.fragmentb.BaseViewModel" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->viewModel.oneSelected()}" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->viewModel.twoSelected()}" />
    </LinearLayout>
</layout>

Extend your ViewModelA,ViewModelB with the BaseViewModel

Related