I have following code for the model view.
When I disable saveViewState = true
or remove it, checkbox?.isChecked
is properly set by epoxy adapter (to true or false, according to isChecked
boolean that is passed to the annotated method). But, when I enable it (set saveViewState = true
), the checkbox?.isChecked
value is always set to false (at least as I see it in the UI, all checkboxes are unchecked).
I've put logs before this.checkbox?.isChecked = isChecked
and after, and I saw that the value passed is correct, and checkbox isChecked
property is set correctly. What I don't understand is why epoxy overrides all that and sets checkbox to an unchecked state (to false), despite having its property set, for example, to a checked state.
I've tried to do a requestModelBuild
on the epoxy view right after models were built, and with some delay, but it didn't help.
@ModelView(saveViewState = true)
class RowView: ConstraintLayout {
constructor(context: Context):
super(context)
constructor(context: Context, attributeSet: AttributeSet):
super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, styleAttr: Int):
super(context, attributeSet, styleAttr)
@TextProp
fun setText(text: CharSequence) {
this.checkbox?.text = text
}
@ModelProp
fun setCheckedState(isChecked: Boolean) {
this.checkbox?.isChecked = isChecked
}
@CallbackProp
fun setOnChangeListener(listener: CompoundButton.OnCheckedChangeListener?) {
listener?.let { this.checkbox?.setOnCheckedChangeListener(it) }
}
}
How do I set checkbox state inside epoxy model view when view state is enabled? Does this issue also happens when EditText is used? And why checkbox label is populated correctly (no empty text, the text passed is shown as it should be)?
As discussed in https://github.com/airbnb/epoxy/issues/681, the property states should be stored elsewhere, and onChangeListener should request model rebuild at the end. i.e "you can't have data provided both by saved state and by a model prop since they conflict, saved state overrides model prop settings".
For this to work, I had to change
@ModelView(saveViewState = true)
class RowView: ConstraintLayout {
to
@ModelView
class RowView: ConstraintLayout {
and implement model rebuild like this
view.rv.buildModelsWith { controller ->
model.items.forEach { item ->
RowViewModel_().id(item.id.name)
.checkedState(model.itemsChosen[item] ?: false)
.onChangeListener { buttonView, isChecked ->
if (buttonView.isShown && buttonView.isPressed) {
model.itemsChosen[item] = isChecked
controller.requestModelBuild()
}
}
.addTo(controller)
}
}
Tested it and it worked.