14

I'm new in data binding , this is my code but I get this error on building

class DatabindingViewModel :ViewModel() {

val currentFruitName:LiveData<String>
    get() = FakeRepository.currentName

fun changeNameOnClick()=FakeRepository.changeRandomFoodName()

//two way LiveData
@Bindable
val editTextContext= MutableLiveData<String>()

private val _displayEditTexfContent=MutableLiveData<String>()
val displayEditTexfContent:LiveData<String>
    get()=_displayEditTexfContent

fun onDisplayEtText(){
    _displayEditTexfContent.value=editTextContext.value
}

this is my xml layout code :

    <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="binding"
            type="ir.persiandesigners.myapplication.databinding.viewmodel.DatabindingViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="50dp"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="32dp"
            android:layout_marginEnd="50dp"
            android:layout_marginRight="50dp"
            android:text="@{binding.currentFruitName}"
            android:textAppearance="@style/TextAppearance.AppCompat.Display1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:onClick="@{()->binding.changeNameOnClick()}"
            android:text="Get Random  Name"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="60dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="@={binding.editTextContext}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/button" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="24dp"
            android:layout_marginEnd="8dp"
            android:layout_marginRight="8dp"
            android:onClick="@{()->binding.onDisplayEtText()}"
            android:text="Change Display Text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/editText" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

this is the code I've in the activity:

val viweModel= ViewModelProviders.of(this)
            .get(DatabindingViewModel::class.java)

    DataBindingUtil.setContentView<ActvitiyDatadindingBinding>(
            this,R.layout.actvitiy_datadinding)
            .apply {
                this.setLifecycleOwner( this@DataBindingAct)
                this.binding=viweModel
            }

    viweModel.editTextContext.observe(this, Observer{
        Toast.makeText(this@DataBindingAct,it ,Toast.LENGTH_LONG).show()
    })

when I want to build the project and run it , I get this error :

e: error: Bindable must be on a member in an Observable class. DatabindingViewModel is not Observable

could you help me ?

I've tried to clean the project , rebuild and so on but there is an error in my code that I couldn't find

could you help me ?

a_local_nobody
  • 7,947
  • 5
  • 29
  • 51
Navid Abutorab
  • 1,667
  • 7
  • 31
  • 58
  • Quick googling the error "Bindable must be on a member in an Observable class" brought me multiple results, including this post that may be help you. https://www.javatips.net/api/android.databinding.bindable – fluidguid Jun 11 '19 at 12:53
  • @fluidguid I've googled but couldnt solve my problem – Navid Abutorab Jun 11 '19 at 12:58
  • 1
    I think the error explains it all. Your `ViewModel` should implement `Observable`, like `BaseObservable`. See [here](https://developer.android.com/topic/libraries/data-binding/two-way#two-way-custom-attrs) – Sanlok Lee Jun 12 '19 at 17:42

3 Answers3

25

Just remove @Bindable annotation from Viewmodel and your code will run successfully and error will be resolved.

The @Bindable annotation should only be be applied when you are accessing getter method while extending BaseObservable class which itself implements Observable interface for observing data.

Here LiveData itself is an observable data holder class

So, you don't need to implement @Bindable and BaseObservable class for observing data.

docs: https://developer.android.com/reference/android/databinding/Bindable

I hope things are clear now..

Gaurav Singh
  • 1,177
  • 12
  • 16
6

You have to implement Observable Interface and add its methods

here is mine,

class MainViewModel: ViewModel(), Observable { 

private val callbacks: PropertyChangeRegistry by lazy { PropertyChangeRegistry()}

    override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
        callbacks.add(callback)
    }

    override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
        callbacks.remove(callback)
    }
}// class ends here
MaartenDev
  • 5,631
  • 5
  • 21
  • 33
Sumit Jangir
  • 61
  • 1
  • 4
-1

Do the following step-by-step:

  • Clean Project
  • Rebuild Project
  • Invalidate Caches / Restart

Trust me, it should work. I know the solution is simple but I also wasted my 3 hours 'cuz of this. Follow these 3 steps and you should be good to go.

Nirmesh
  • 7
  • 2