Reputation: 8177
I have an activity that should display a non-fixed amount of fragments. Each fragment will receive an element of a MutableList of Customer
and it needs to have its components bound to a property in this Customer
class.
I've created the class like this:
class Customer constructor(
val name: LiveData<String>
val email: LiveData<String>
)
In my ViewModel
I've created the MutableList
of Customer
:
class CustomerViewModel: ViewModel() {
val customers: MutableList<Customer> = mutableListOf()
}
Then I dynamically create the Fragments:
for (i in 0..customerCount) {
val fragment = FragmentCustomer.newInstance(viewModel.customers.get(i))
supportFragmentManager.beginTransaction()
.add(R.id.fragmentContainer, fragment, "FragmentCustomer_$i")
.commit()
}
The customer instance is stored in a variable in the Fragment and then I do the DataBindingUtil.inflate
:
var binding: FragmentCustomerBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_customer, container, false)
var view = binding.root
binding.model = palavra
return view
And in the Fragment's layout:
<EditText
android:id="@+id/nameTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="@{model.name}"
android:onTextChanged="@={model.name}" />
This is causing ****/ data binding error ****msg:The expression modelName.getValue() cannot be inverted: There is no inverse for method getValue, you must add an @InverseMethod annotation to the method to indicate which method should be used when using it in two-way binding expressions
.
How can I fix this? And a "bonus" question, do I still have to store view content using savedState on events like onDestroy
or ViewModel will handle that for me?
Upvotes: 0
Views: 1333
Reputation: 16920
For your first question, the values should be MutableLiveData types instead of just LiveData, otherwise there will be no setter exposed:
class Customer constructor(
val name: MutableLiveData<String>
val email: MutableLiveData<String>
)
Don't forget to set the lifecycle owner on the binding after inflating it, because otherwise the view will not be updated when the data changes.
For your bonus question: You should store the ViewModel as a variable in your fragment. This ensures that it will keep the data when the view is being destroyed, but the fragment is kept. Upon destroy, the live data instances will be cleaned up, because they know about the lifecycle you provided to the binding.
Optimally, the Customer class should not have modifiable properties, because this makes it editable to everyone, without the guarantee of saving the changes. But that's a different story.
Upvotes: 1