Search code examples
androidandroid-databindingandroid-architecture-componentsandroid-jetpack

How to fix cannot find symbol view-model-name-BindingImpl when using two-way databinding in Android


I am implementing Two-Way DataBinding with Android Architecture Components using LiveData and ViewModel, but when I build the project it gives

error: cannot find symbol
import package.[layout_name]BindingImpl;

in DataBinderMapperImpl.java

I followed official documentation and looked at SO for answers but none of them had workable solutions.

already tried this one and this one

layout.xml

    <data>
        <import type="package.ViewModel" /> // this line was added from an answer but didn't work
        <variable
            name="model"
            type="package.ViewModel"/>
    </data>

// an input field I want to bind data with
<androidx.appcompat.widget.AppCompatAutoCompleteTextView
                    android:id="@+id/email"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@={model.email}" // if I remove this line, builds fine
                    android:hint="@string/prompt_email"
                    android:inputType="textEmailAddress"
                    android:maxLines="1"
                    android:singleLine="true" />

Extending my ViewModel from AndroidViewModel instead of BaseObservable as mentioned in documentation

ViewModel.kt

    private val email: MutableLiveData<String> by lazy { MutableLiveData<String>() }
    @Bindable // tried to change the return type to String, still no luck
    fun getEmail(): LiveData<String> {
        return email
    }

    fun setEmail(email: String) {
        this.email.value = email
    }

This is how I bind ViewModel with View

Activity.kt

binding.model = ViewModelProviders.of(this, ViewModelProvider.AndroidViewModelFactory
            .getInstance(application))
            .get(LoginViewModel::class.java)

What am I missing? Already included all things pre-databinding and if I had replaced ViewModel in layout with a data class and tried to get data from it, that works fine but with @{} in layout

EDIT

Okay, so when I expose email as public, it compiles and binding works, but I can't make its setter and getter public, I mean when I try to expose it from its getter and setter, IDE says that these are already private functions and cannot be overriden?

How can I make this property expose through functions?


Solution

  • Found the answer on Reddit.

    For two-way databinding to work, you have to expose your fields and they should be MutableLiveData like

    val email = MutableLiveData<String>()
    

    since kotlin already has get and set properties, they'll be used by Binding classes for fields