ateebahmed
ateebahmed

Reputation: 182

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?

Upvotes: 0

Views: 1034

Answers (3)

Eggakin Baconwalker
Eggakin Baconwalker

Reputation: 583

I was having the same problem and none of the solutions presented here worked. In my case, the problem was because I had a Double property.

I changed it to String and it worked.

Upvotes: 1

ateebahmed
ateebahmed

Reputation: 182

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

Upvotes: 0

Jeel Vankhede
Jeel Vankhede

Reputation: 12138

You can use getter of particular variable directly using get() method to variable (also works for setter too as set(value)) like below :

@get:Bindable // We make getter method bindable for data-binding
val email = MutableLiveData<String>()
    get() { // Try to provide getter method like this
        return field as LiveData<String>
    }
    set(data) { // Try to provide setter method like this
        if(field.value != data.value) // To avoid infinite loop
            field.value = data.value
    }

Upvotes: 0

Related Questions