Different ViewModel instance for a layout when I reuse it multiple times?

Viewed 44

I want to use a smaller layout with its own view model a few times within my main layout like so (using LinearLayout for simplicity):

sub_layout.xml

<layout>
    <data>
        <variable
            name="subVm"
            type="...SubViewModel" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/sub_tv_value"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="@{subVm.valueString}" />

        <Button
            android:id="@+id/sub_btn_do_something"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{subVm.doSomethingString}" />
    </LinearLayout>
</layout>

main_activity.xml

<layout>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            layout="@layout/sub_includable_view"
            android:id="@+id/main_v_0"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <include
            layout="@layout/sub_includable_view"
            android:id="@+id/main_v_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</layout>

SubViewModel.kt

class SubViewModelFactory(private val number: Int) : ViewModelProvider.Factory {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(SubViewModel::class.java)){
            return SubViewModel(number) as T
        }

        throw IllegalArgumentException("Unknown SubViewModel class")
    }
}

class SubViewModel(value: Int) : ViewModel() {
    val valueString: String = value.toString()
    val doSomethingString: String = "Do Something $value"
}

However, when I set the view model of those individual layouts, each view appears to be referencing the same SubViewModel instance.

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private val subVm0: SubViewModel by viewModels() {
        SubViewModelFactory(0)
    }

    private val subVm1: SubViewModel by viewModels() {
        SubViewModelFactory(1)
    }

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        binding.mainV0.subVm = subVm0
        binding.mainV1.subVm = subVm1
    }
}

Results:

enter image description here

Is it possible to reuse a layout multiple times within a layout, and have each of those layouts have a different instance of the SubViewModel class? Or will they always reference the same instance this way?

We could just implement the desired functionality in the main_activity.xml with one MainViewModel but I'm curious if this way of code-reuse is possible. Any ideas? Thanks!

0 Answers
Related