Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UI not updated when ViewModel value changed

I have created sample app to demo my question:

A TextView and a Button, text view visibility is bound to viewModel.bar

I want the button to switch the value of viewModel.bar when clicked and the UI to get updated as well.

However, this is not happening. The value is changed but the UI is not updated.

Layout File:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <import type="android.view.View"/>
        <variable name="viewModel"
                  type="com.example.bindingone.MainViewModel"/>
    </data>

    <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">

        <TextView
                android:id="@+id/text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hello World"
                android:visibility="@{viewModel.bar ? View.VISIBLE : View.GONE}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Button
                android:text="Update UI"
                android:onClick="clicked"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

    </android.support.constraint.ConstraintLayout>

</layout>

MainActivity File:

class MainActivity : AppCompatActivity() {

    private val viewModel = MainViewModel()

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.viewModel = viewModel
    }

    fun clicked(v: View) {
        viewModel.bar.value = viewModel.bar.value?.not() ?: false
    }
}

MainViewModel file:

class MainViewModel : ViewModel() {
    var bar = MutableLiveData<Boolean>()
}
like image 845
malhobayyeb Avatar asked Dec 31 '18 10:12

malhobayyeb


1 Answers

After creating binding, add this line binding.setLifecycleOwner(this).

/**
 * Sets the {@link LifecycleOwner} that should be used for observing changes of
 * LiveData in this binding. If a {@link LiveData} is in one of the binding expressions
 * and no LifecycleOwner is set, the LiveData will not be observed and updates to it
 * will not be propagated to the UI.
 *
 * @param lifecycleOwner The LifecycleOwner that should be used for observing changes of
 *                       LiveData in this binding.
 */
@MainThread
public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner)
like image 164
Dewey Reed Avatar answered Sep 28 '22 07:09

Dewey Reed