1

MutableLiveData value is not being filled when I'm trying to use data binding to do it.

When I use MutableLiveData in primary objects like Strings, it works fine. But if I try to use with a custom object the MutableLiveData#value is getting null

class MyViewModel(application: Application) : AndroidViewModel(application) {

    val data: LiveData<Model> = MutableLiveData<Model>()

    fun save() {
        // ** ERROR HERE - At this point data.value is NULL
        data.value?.let { Repository().insert(it) }
    }
}

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

    <data>
        <variable
            name="viewModel"
            type="<my_path>.ViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="parent"
            android:text="@={viewModel.data.name}"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

@Entity
data class Model(
    @PrimaryKey(autoGenerate = true) var uid: Long? = -1,
    @ColumnInfo(name = "name") var name: String? = "",
    ...
)

class RegisterActivity : AppCompatActivity() {

    private val viewModel by lazy { MyViewModel(application) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityRegisterBinding = DataBindingUtil.setContentView(this, R.layout.activity_register)
        binding.viewModel = viewModel
        binding.executePendingBindings()
    }
}

Getting the MutableLiveData#value at MyViewModel#save to persist the data, the value is returning null.

Bruno Martins
  • 1,347
  • 2
  • 11
  • 32

1 Answers1

2

I don't think data binding can work in such a way out of the box. Some alternatives are:

  • Declare a LiveData for each field, and use a MediatorLiveData to subscribe to them an update your Model instance
  • Declare multiple Observable fields to store the data, collect it and construct a Model instance in your save() method
Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
  • Giz, but whether I have to modify my Model object, I've to change each view model that used it? What about DRY, should I forget about it? – Bruno Martins Jan 26 '19 at 23:57
  • Maybe you can do e research on custom binding adapters and something useful can pop up. – Danail Alexiev Jan 27 '19 at 09:31
  • 1
    when having two-way databinding (`@=`) your `LiveData` has to have the same type (in this case `String`) .. therefore it will work for you if you have `val data = MutableLiveData()` .. in your `save()` method you can then create your object – mlykotom Jan 31 '19 at 22:09