comcom.airbnb.epoxy.ImmutableModelException: Model was changed before it could be diffed
See original GitHub issueI am using TypedEpoxyController and i want to update item of my gridview. I have a model with epoxy attribute in it. When i changing data in this attribute object and calling setData on TypedEpoxyController i am getting such exception:
comcom.airbnb.epoxy.ImmutableModelException: Model was changed before it could be diffed 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.
As i see setData of TypedEpoxyController calls requestModelBuild and prevents from calling it directly. So why i am getting this exception and how i can update cell in gridview using epoxy?
Issue Analytics
- State:
- Created 6 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
Epoxy updating the epoxy attributes in the models once they ...
App has crashed, executing CustomActivityOnCrash's UncaughtExceptionHandler com.airbnb.epoxy.ImmutableModelException: The model was changed ...
Read more >EpoxyModel.isDebugValidationEnabled - airbnb/epoxy
This is used internally by generated models to do validation checking when * "validateEpoxyModelUsage" is enabled and the model is used with a...
Read more >Epoxy: Airbnb's View Architecture on Android - Medium
Introducing Epoxy: github.com/airbnb/epoxy ... However, Epoxy adds a diffing algorithm to detect changes in models and only update views ...
Read more >EpoxyController.java example - Javatips.net
package com.airbnb.epoxy; import android.os. ... so any updates to data can be completely finished before // the models are built. if (hasBuiltModelsEver) ...
Read more >How to build your complex UI with Epoxy - Factory.dev
The Airbnb team designed Epoxy in 2016, and since then is upgrading. ... will have a setter and will be bound when the...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I’m guessing
image
is some field on your model?This doesn’t work - you can’t change the model after it is created. Another issue here is that you are starting the glide load for every single model in the list, that is hugely inefficient; you only want glide to start loading once the item is on screen.
what you should do instead is pass the image url to the model, and load it from there. That way the image is only loaded once the view is bound on screen.
We use glide as well, and set up a simple custom view that extends ImageView, takes a url, and loads the image. You can also use binding adapters (https://github.com/bumptech/glide/issues/932)
I also recommend clearing the imageview when the view is recycled.
On a separate note, you shouldn’t have to concatenate your ids like
id("Andi" + it.andiId)
. there are several id overloads likeid(String, Long)
to avoid creating a new stringyou’re right the problem is
photo.setSelected(!photo.isSelected);
. like the error says, you can’t change data in the model. that data must be treated as immutable.How you structure that is up to you, but I can offer a few suggestions:
You could set up the model to have an extra attribute for whether it is selected
Then change the controller to pass whether each item is selected. You will have to change your data structure to track that.
Using kotlin data classes makes this easy
Alternatively if you want to keep the
isSelected
field inside the Photo class you can do that, but in your bus callback you will need to create a new photo object and update your data list with it. You cannot update the existing photo object. They must be immutable. Using Kotlin data classes makes that trivial and forces you to do it correctly.Personally I don’t think it makes sense to couple the view state of whether something is selected inside the data model representing it. It is simpler, but not a good pattern.