Другой экземпляр ViewModel для макета, когда я повторно использую его несколько раз?

#android #layout #data-binding #include #viewmodel

Вопрос:

Я хочу несколько раз использовать меньший макет с собственной моделью представления в моем основном макете, например ( LinearLayout для простоты):

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"
}
 

Однако, когда я устанавливаю модель представления этих отдельных макетов, кажется, что каждое представление ссылается на один и тот же SubViewModel экземпляр.

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
    }
}
 

Результаты:

введите описание изображения здесь

Можно ли повторно использовать макет несколько раз в макете, и чтобы каждый из этих макетов имел другой экземпляр SubViewModel класса? Или они всегда будут ссылаться на один и тот же экземпляр таким образом?

Мы могли бы просто реализовать желаемую функциональность в main_activity.xml с одним MainViewModel , но мне любопытно, возможен ли такой способ повторного использования кода. Есть какие-нибудь идеи? Спасибо!

Комментарии:

1. AFAIK, данная область (в данном случае ваша деятельность) может иметь только одну модель представления данного типа. Таким образом, вы subVm0 создаете этот экземпляр и subVm1 извлекаете существующий экземпляр. Вам нужно будет использовать разные области, например, чтобы каждая из них была во фрагменте, и выполнить сборку фрагментов.