Search code examples
androidandroid-layoutandroid-databindingandroid-viewmodel

How do I use Data Binding with reused layouts?


Let's say I have the following layout files:

first_layout.xml

<layout>
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
      <TextView 
          android:id="@+id/title_one"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="First layout title"/>
      <include
          layout="@layout/reusable_layout"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />
  </LinearLayout>
</layout>

second_layout.xml

<layout>
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
      <TextView 
          android:id="@+id/title_two"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Second layout title"/>
      <include
          layout="@layout/reusable_layout"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />
  </LinearLayout>
</layout>

reusable_layout.xml

<layout>
    <TextView 
        android:id="@+id/text_to_replace"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="replace me"/>
</layout>

...and that I have two different ViewModels (FirstLayoutViewModel and SecondLayoutViewModel, each with a different String property). I want to use Data Binding to bind each ViewModel's string property to the text_to_replace element in reusable_layout.xml.

How can I do this? Normally, I would declare a variable in a <data> tag and assign the type to the appropriate ViewModel but how can I do this if the layout (reusable_layout.xml) is being used multiple times? How will it know which ViewModel type to use?

In this example, I could just use a different TextView for the first_layout and second_layout layout instead of importing a layout but in my real project, the layout I want to reuse is much more complicated and it makes sense to reuse.

Any help would be great. Thanks!


Solution

  • You're saying you just need a to display a String so instead of passing a FirstLayoutViewModel and SecondLayoutViewModel, you should pass the String to your reusable_layout.

    <layout>
        <data>
            <variable name="myText" type="String> />
        </data>
        <TextView 
            android:id="@+id/text_to_replace"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{myText}"/>
    </layout>
    

    More details: how to pass data in includes

    class MyViewModel1 : ViewModel {
        
        private val _myLiveData = MutableLiveData<String>()
        val myLiveData: LiveData<String>
            get() = _myLiveData
    
        init {
            //Assign MyLiveData
        }
    }
    
    class MyViewModel2 : ViewModel {
        
        private val _mySecondLiveData = MutableLiveData<String>()
        val mySecondLiveData: LiveData<String>
            get() = _mySecondLiveData
    
        init {
            //Assign MyLiveData
        }
    }
    

    FirstLayout:

    <layout>
        <data>
            <variable name="viewModel" type="MyViewModel1"/>
        </data>
      <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
          <TextView 
              android:id="@+id/title_one"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="First layout title"/>
          <include
              layout="@layout/reusable_layout"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              app:myText="@{viewModel.myLiveData}"
               />
      </LinearLayout>
    </layout>
    

    SecondLayout:

    <layout>
        <data>
            <variable name="viewModel" type="MyViewModel2"/>
        </data>
    
      <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
          <TextView 
              android:id="@+id/title_one"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="First layout title"/>
          <include
              layout="@layout/reusable_layout"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              app:myText="@{viewModel.mySecondLiveData}"
               />
      </LinearLayout>
    </layout>