Search code examples
androidkotlindata-bindingandroid-livedataandroid-databinding

DataBinding doesn't update value when changing LiveData


I want the value to increase when I press the button and write it in the textview. However, the code below shows the increasing value as Log But, on screen, the value in textview does not change. I'm not sure what's wrong. Please let me know if you know.

Fragment.kt

class SettingFragment : Fragment(), View.OnClickListener {

    companion object {
        fun newInstance() = SettingFragment()
        private val TAG = "SettingFragment"
    }

    private lateinit var viewModel: SettingViewModel
    private lateinit var binding: FragmentSettingBinding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_setting, container, false)
        return binding.root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this).get(SettingViewModel::class.java)
        binding.lifecycleOwner = this
        binding.button.setOnClickListener(this)
    }

    override fun onClick(v: View?) {
        viewModel.increase()
        Log.d(TAG, "Log Data" + viewModel.testInt.value)
    }

}

FragmentViewModel

class SettingViewModel : ViewModel() {


    val testInt: MutableLiveData<Int> = MutableLiveData()

    init {
        testInt.value = 0
    }

    fun increase() {
        testInt.value = testInt.value?.plus(1)
    }
}

fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="viewModel"
            type="com.example.ui.setting.SettingViewModel" />
    </data>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".ui.setting.SettingFragment">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(viewModel.testInt)}" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    </LinearLayout>
</layout>

Solution

  •     <variable
            name="viewModel"
            type="com.example.ui.setting.SettingViewModel" />
    

    This viewModel variable doesn't bind to a certain variable programmatically. So, when the value incremented, it won't reflect to the layout.

    To fix this set the fragment's viewModel to this value:

        viewModel = ViewModelProvider(this).get(SettingViewModel::class.java)
        binding.viewModel = viewModel // <<<<< Here is the change
        binding.lifecycleOwner = this
        binding.button.setOnClickListener(this)
    

    Side note:

    You shouldn't use onActivityCreated() as it's is deprecated as of API level 28; you can normally its part of code to onCreateView(). And you can check here for other alternatives.