com.airbnb.epoxy.ImmutableModelException: The model was changed between being bound and when models were rebuilt
See original GitHub issueHello,
I’m working on a project and I having some trouble with rebuilding the Views through EpoxyController.
Everytime I change some of the data inside the View and call the TypedEpoxyController SetData my app crashes with the error:
com.airbnb.epoxy.ImmutableModelException: The model was changed between being bound and when models were rebuilt Position: 0 Model: // Model Data Here
Epoxy attribute fields on a model cannot be changed once the model is added to a controller. Check that these fields are not updated, or that the assigned objects are not mutated, outside of the buildModels method. The only exception is if the change is made inside an Interceptor callback. Consider using an interceptor if you need to change a model after it is added to the controller and before it is set on the adapter. If the model is already set on the adapter then you must call requestModelBuild
instead to recreate all models.
Code:
class CheckoutFragment : ContainerFragment(), CheckoutController.Listener
{
override val TAG: String = CheckoutFragment::class.java.name
lateinit var viewModel: CheckoutViewModel
private lateinit var checkoutProducts: MutableList<Product>
private lateinit var controller: CheckoutController
override val toolbarLayout: InteraToolbar?
get() = toolbar
companion object {
fun newInstance(backNavigationEnabled: Boolean = false) = CheckoutFragment().apply {
arguments = bundleOf(BACK_NAVIGATION_ENABLED to backNavigationEnabled)
}
}
override fun layoutRes(): Int = R.layout.fragment_checkout
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
super.onViewCreated(view, savedInstanceState)
checkoutProducts = mutableListOf()
initViewModel()
initRecyclerView()
}
private fun initViewModel()
{
viewModel= ViewModelProviders.of(this).get(CheckoutViewModel::class.java)
viewModel.productLiveData.observe(this, Observer {
checkoutProducts = it.toMutableList()
updateController()
})
viewModel.applyService()
}
private fun initRecyclerView() {
controller = CheckoutController(this)
erv_product.itemAnimator?.changeDuration = 0
erv_product.setController(controller)
updateController()
}
private fun setDataAvailableLayout(isAvailable: Boolean) {
group_calculate_shipping.showOrHide(isAvailable)
group_content_layout.showOrHide(isAvailable) {
cl_root.backgroundColorResource = R.color.white
btn_proceed_with_order.textResource = R.string.proceed_with_order
rg_payment_type.selectViewProgrammatically(R.id.rb_associated_total_text)
}
tv_no_content.showOrHide(!isAvailable) { //BREAKING HERE!!!
cl_root.backgroundColorResource = R.color.color_f9f7eb
btn_proceed_with_order.textResource = R.string.make_a_wish
}
}
private fun updateController() {
setDataAvailableLayout(checkoutProducts.isNotEmpty())
controller.setData(checkoutProducts) // ERROR HAPPENS HERE AFTER CALLING IT AGAIN
}
override fun onRemoveClick(product: Product) {
viewModel.remove(product)
updateController()// CALL CRASH THE APP
}
override fun onFavoriteClick(product: Product) {
viewModel.changeFavorite(product)
product.isFavorite = !product.isFavorite
updateController() // CALL CRASH THE APP
}
override fun onSelectionCountClick(product: Product) {
val list = (1 .. 20).toList().map { it.toString() }
selector("Select count", list) { dialog, position ->
dialog.dismiss()
val currentSelection = list[position]
val quantity = currentSelection.toIntOrNull().orZero()
viewModel.update(product, quantity)
updateController()// CALL CRASH THE APP
}
}
I am really stuck at this. I tried a bunch of stuff but somehow I could not progress into making my EpoxyModels to update with the new product data.
Thanks in advance
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (2 by maintainers)
these errors should only be thrown when debug validations are enabled, so you can disabled that temporarily while you fix them.
These are errors that you do not want to ignore though, as they are real problems the can lead to your views not working properly
@elihart i am also facing the same issue. I also used the interceptors to update, but no luck. Same error i am getting. If needed i will paste my code. May i get help please ? Why it is so complicated to update models ?? It should be as easy as notifyDataSetChanged, isn’t it ?