title: How to pass data binding variable as xml attribute to custom view
body: <p>I am trying to create a simple form layout that uses a ViewModel containing LiveData to bind to each form field so that the inputted data can persist through configuration changes and back navigation (in the case of a multi-step form). 
  Additionally, I have a custom form field view with its own layout xml to do some required processing. However, I am having difficulty passing data through the form layout to bind to the custom view layout.</p>
  
  <p>Here is a simplified version of my ViewModel, Fragment, Field object and its layout:</p>
  
  <pre><code>class FormViewModel : ViewModel() {
      @Bindable val email = MutableLiveData&lt;String&gt;().apply { value = "" }
  }
  </code></pre>
  
  <pre><code>class FormFragment : BaseFragment() {
  
      private val formViewModel: FormViewModel by lazy {
          ViewModelProviders.of(requireActivity()).get(FormViewModel::class.java)
      }
  
      override fun onCreateView(inflater: LayoutInflater, 
                                container: ViewGroup?, 
                                savedInstanceState: Bundle?) : View? =
          (DataBindingUtil
              .inflate(inflater, R.layout.fragment_form, container, false) as FragmentFormBinding)
              .apply {
                  lifecycleOwner = requireActivity()
                  viewModel = formViewModel
              }
              .root
  }
  </code></pre>
  
  <pre><code>class Field @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
      : LinearLayout(context, attrs, defStyleAttr) {
  
      @Bindable var fieldData: MutableLiveData&lt;String&gt; = MutableLiveData&lt;String&gt;().apply { value = "" }
  
      init {
          val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
          (DataBindingUtil
              .inflate(inflater, R.layout.field, this, true) as FieldBinding)
              .apply { fieldData = this@Field.fieldData }
              .root
      }
  }
  </code></pre>
  
  <p>field.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;layout xmlns:tools="http://schemas.android.com/tools"
          xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  
      &lt;data&gt;
          &lt;variable
                  name="fieldData"
                  type="androidx.lifecycle.MutableLiveData&amp;lt;String&gt;"/&gt;
      &lt;/data&gt;
  
      &lt;LinearLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"&gt;
          &lt;com.google.android.material.textfield.TextInputLayout
                  android:id="@+id/inputField"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  tools:hint="Email"&gt;
  
              &lt;com.google.android.material.textfield.TextInputEditText
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:hint="Email"
                      android:text="@={ fieldData }" /&gt;
  
          &lt;/com.google.android.material.textfield.TextInputLayout&gt;
      &lt;/LinearLayout&gt;
  &lt;/layout&gt;
  </code></pre>
  
  <p>What I would like to do is bind the live data from the ViewModel to a form field by passing it as an attribute to an instance of my custom form field in the form xml like so:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"&gt;
      &lt;data&gt;
          &lt;variable name="viewModel"
                  type="packageName.FormViewModel"/&gt;
      &lt;/data&gt;
  
      &lt;LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical"
              android:padding="32dp"&gt;
  
          &lt;packageName.Field
                  android:id="@+id/emailField"
                  app:fieldData="@{ viewModel.email }"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginTop="60dp" /&gt;
  
      &lt;/LinearLayout&gt;
  &lt;/layout&gt;
  </code></pre>
  
  <p>However, when I try this I get the following error:</p>
  
  <pre><code>E/AndroidRuntime: FATAL EXCEPTION: main
      Process: packageName, PID: 27543
      java.lang.RuntimeException: Failed to call observer method
          at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:226)
          at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
          at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
          at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:37)
          at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
          at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:188)
          at androidx.databinding.ViewDataBinding.setLifecycleOwner(ViewDataBinding.java:394)
          at packageName.FormFragment.onCreateView(FormFragment.kt:24)
          at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2669)
          at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1321)
          at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2515)
          at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2290)
          at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2246)
          at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2143)
          at androidx.fragment.app.FragmentManager$3.run(FragmentManager.java:417)
          at android.os.Handler.handleCallback(Handler.java:739)
          at android.os.Handler.dispatchMessage(Handler.java:95)
          at android.os.Looper.loop(Looper.java:135)
          at android.app.ActivityThread.main(ActivityThread.java:5221)
          at java.lang.reflect.Method.invoke(Native Method)
          at java.lang.reflect.Method.invoke(Method.java:372)
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
       Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter &lt;set-?&gt;
          at packageName.Field.setFieldData(Field.kt)
          at packageName.databinding.FragmentFormBindingImpl.executeBindings(FragmentFormBindingImpl.java:127)
          at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:472)
          at androidx.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:444)
          at androidx.databinding.ViewDataBinding$OnStartListener.onStart(ViewDataBinding.java:1685)
          at java.lang.reflect.Method.invoke(Native Method)
          at java.lang.reflect.Method.invoke(Method.java:372)
          at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:216)
          at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194) 
          at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185) 
          at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:37) 
          at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361) 
          at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:188) 
          at androidx.databinding.ViewDataBinding.setLifecycleOwner(ViewDataBinding.java:394) 
          at packageName.FormFragment.onCreateView(FormFragment.kt:24) 
          at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2669) 
          at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1321) 
          at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2515) 
          at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2290) 
          at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2246) 
          at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2143) 
          at androidx.fragment.app.FragmentManager$3.run(FragmentManager.java:417) 
          at android.os.Handler.handleCallback(Handler.java:739) 
          at android.os.Handler.dispatchMessage(Handler.java:95) 
          at android.os.Looper.loop(Looper.java:135) 
          at android.app.ActivityThread.main(ActivityThread.java:5221) 
          at java.lang.reflect.Method.invoke(Native Method) 
          at java.lang.reflect.Method.invoke(Method.java:372) 
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
  </code></pre>
  
  <p>As an alternative this can easily be achieved by including the field layout instead like the following but in this case I cannot do any of the setup I would like to do in the Field object</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"&gt;
  
      &lt;data&gt;
          &lt;variable name="viewModel"
                  type="packageName.FormViewModel"/&gt;
      &lt;/data&gt;
  
      &lt;LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical"
              android:padding="32dp"&gt;
  
          &lt;include
                  layout="@layout/field"
                  android:id="@+id/emailField"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  app:fieldData="@{ viewModel.email }" /&gt;
      &lt;/LinearLayout&gt;
  &lt;/layout&gt;
  </code></pre>
  
  <p>I'm guessing has to do with the order in which the xml is inflated and data binding variable generated but I am having difficulty debugging</p>
  
  <p><strong><em>EDIT:</em></strong> I just noticed I am not setting the lifecycle owner in the Field data binding but the issue arises even if I am not inflating the layout in the Field class</p>