- Fix some synchronization issues with the parallel Epoxy processing option
- Add view visibility checks to EpoxyVisibilityItem and decouple RecyclerView #1052
- Incremental annotation processing for faster builds
- Support for Android Jetpack Paging v3 library in new
epoxy-paging3
artifact - Model group building with Kotlin DSL (#1012)
- A new annotation processor argument
logEpoxyTimings
can be set to get a detailed breakdown of how long the processors took and where they spent their time (off by default) - Another new argument
enableParallelEpoxyProcessing
can be set to true to have the annotation processor process annotations and generate files in parallel (via coroutines).
You can enable these processor options in your build.gradle file like so:
project.android.buildTypes.all { buildType ->
buildType.javaCompileOptions.annotationProcessorOptions.arguments =
[
logEpoxyTimings : "true",
enableParallelEpoxyProcessing : "true"
]
}
Parallel processing can greatly speed up processing time (moreso than the incremental support), but given the hairy nature of parallel processing it is still incubating. Please report any issues or crashes that you notice. (We are currently using parallel mode in our large project at Airbnb with no problems.)
- Add options to skip generation of functions for getters, reset, and method overloads to reduce generated code
- New annotation processor options are:
- epoxyDisableGenerateOverloads
- epoxyDisableGenerateGetters
- epoxyDisableGenerateReset
- New annotation processor options are:
- Synchronize ListUpdateCallback and PagedListModelCache functions (#987)
- Avoid generating bitset checks in models when not needed (reduces code size)
- Fix minor memory leak
-
Annotations that previously targeted package elements now target types (classes or interfaces). This includes:
EpoxyDataBindingPattern
,EpoxyDataBindingLayouts
,PackageModelViewConfig
,PackageEpoxyConfig
This was necessary to work around an incremental annotation processor issue where annotation on package-info elements are not properly recompiled -
In order to enable incremental annotation processing a change had to be made in how the processor of
@AutoModel
annotations work. If you use@AutoModel
in an EpoxyController the annotated Model types must be either declared in a different module from the EpoxyController, or in the same module in the same java package.Also make sure you have kapt error types enabled.
However, generally
@AutoModel
is considered legacy and is not recommended. It is a relic of Java Epoxy usage and instead the current best practice is to use Kotlin with the Kotlin model extension functions to build models. -
Removed support for generating Epoxy models from Litho components
- PackageModelViewConfig can now be applied to classes and interfaces in addition to package-info.java
Fixes:
- An occasional processor crash when the option to log timings is enabled
- Incremental annotation processing of databinding models would fail to generate models (#1014)
Breaking!
- The annotation that support databinding,
EpoxyDataBindingLayouts
andEpoxyDataBindingPattern
, must now be placed on a class or interface instead of in apackage-info.java
file. The interface or class must be in Java, Kotlin is not supported. This is necessary to support incremental processing.
Example usage:
package com.example.app;
import com.airbnb.epoxy.EpoxyDataBindingLayouts;
import com.airbnb.epoxy.EpoxyDataBindingPattern;
@EpoxyDataBindingPattern(rClass = R.class, layoutPrefix = "my_view_prefix")
@EpoxyDataBindingLayouts({R.layout.my_model_layout})
interface EpoxyDataBindingConfig {}
Fixes:
- Synchronize ListUpdateCallback and PagedListModelCache functions (#987)
- 4.0.0.beta1 generating duplicate method layout(int) #988
- Sort functions in generated kotlin extension function files deterministically to prevent generated sources from changing
- Avoid generating bitset checks in models when not needed
- Add options to skip generation of functions for getters, reset, and method overloads to reduce generated code
New annotation processor options are:
- epoxyDisableGenerateOverloads
- epoxyDisableGenerateGetters
- epoxyDisableGenerateReset
These can also be controlled (and overridden) on a per package level with the PackageModelViewConfig
package annotation.
- Support for incremental annotation processing as an Aggregating processor (#972)
- Removed Litho support
- A new annotation processor argument
logEpoxyTimings
can be set to get a detailed breakdown of how long the processors took and where they spent their time (off by default) - Another new argument
enableParallelEpoxyProcessing
can be set to true to have the annotation processor process annotations and generate files in parallel (via coroutines).
You can enable these processor options in your build.gradle file like so:
project.android.buildTypes.all { buildType ->
buildType.javaCompileOptions.annotationProcessorOptions.arguments =
[
logEpoxyTimings : "true",
enableParallelEpoxyProcessing : "true"
]
}
Parallel processing can greatly speed up processing time (moreso than the incremental support), but given the nature of parallel processing it is still incubating. Please report any issues or crashes that you notice. (We are currently using parallel mode in our large project at Airbnb with no problems.)
In order to enable incremental annotation processing a change had to be made in how the processor of
@AutoModel
annotations work. If you use @AutoModel
in an EpoxyController the annotated Model types
must be either declared in a different module from the EpoxyController, or in the same module in the same java package.
Also make sure you have kapt error types enabled.
However, generally @AutoModel
is considered legacy and is not recommended. It is a relic of Java Epoxy usage
and instead the current best practice is to use Kotlin with the Kotlin model extension functions to build models.
- Introduce partial impression visibility states (#973)
- Fix sticky header crash (#976)
- Carousel building with Kotlin DSL (#967)
- Android ViewBinding: added an example in the sample project. (#939)
- Fix setter with default value lookup in kotlin 1.4 (#966)
- Change "result" property name in generated model (#965)
- Add support for Sticky Headers (#842)
- Use measured width/height if it exists in Carousel. (#915)
- Add a getter to EpoxyViewHolder.getHolder(). (#952) (#953)
- Fix visibility tracking during RecyclerView animations (#962)
- Fix leak in ActivityRecyclerPool ((#906)
- Rename ResultCallack to ResultCallback in AsyncEpoxyDiffer (#899)
- Fix incorrect license attributes in POM file (#898)
- Fix reading EpoxyDataBindingPattern enableDoNotHash (#837)
- Make EpoxyRecyclerView.setItemSpacingPx() open (#829)
- Use same version for Mockito Core and Inline (#860)
- Minor documentation and variable name updates. (#870)
- Move epoxy-modelfactory tests to their own module (#834)
- Remove executable bit from non-executable files (#864)
- Various repo clean ups and version bumps
- Add support for Kotlin delegation via annotated interface properties #812
- Fix checked change crash and improve debug errors #806
- Remove extra space in Kotlin extensions #777
- Update project to AGP 3.5, Kotlin 1.3.50, Gradle 5.6
- New Add a method to request visibility check externally (airbnb#775)
- New Preloader system with glide extensions airbnb#766
- Fixed model click listener crashing on nested model airbnb#767
- Bumped Kotlin to 1.3.31
- New Converted EpoxyRecyclerView to Kotlin (you may need to update your usage for this). Also added built in support for
EpoxyRecyclerView#withModels
for easy inline model building with Kotlin. - Fixed Crashes in visibility tracking
- Fixed Kotlin default param handling had issues with overloaded functions
- New Support kotlin default parameters in @ModelView classes (airbnb#722)
- New Generate OnModelCheckedChangeListener override for props of type
CompoundButton.OnCheckedChangeListener
(airbnb#725) - New Extract ID generation methods to new public IdUtils class (airbnb#724)
- Changed Reset controller state on failed model build (airbnb#720)
- Changed Disabled the auto-detach behavior on Carousels by default (airbnb#688)
- Fixed Two issues related to the recent EpoxyModelGroup changes (airbnb#676)
- New Enable recycling of views within EpoxyModelGroup (airbnb#657)
- New Add support to tracking visibility in nested RecyclerViews (airbnb#633)
- New Add method to clear cache in paging controller (airbnb#586)
- Fix Crashes from synchronization in PagedListEpoxyController (airbnb#656)
- Fix Get onSwipeProgressChanged callbacks on return to original item position (airbnb#654)
- Fix Memory leak in debug mode is removed (airbnb#613)
- Fix For visibility callbacks, wrong visibility when the view becomes not visible (airbnb#619)
-
Breaking Migrated to androidx packages (Big thanks to jeffreydelooff!)
-
Breaking The
Carousel.Padding
class changed the ordering of its parameters to match Android's ordering of "left, top, right, bottom". (airbnb#536 thanks to martinbonnin)This change won't break compilation, so you must manually change your parameter ordering, otherwise you will get unexpected padding results.
This release adds built in support for monitoring visibility of views in the RecyclerView. (airbnb#560)
Usage instructions and details are in the wiki - https://github.com/airbnb/epoxy/wiki/Visibility-Events
Huge thanks to Emmanuel Boudrant for contributing this!
-
New A new
PagedListEpoxyController
to improve integration with the Android Paging architecture component (#533 Thanks to Yigit!) With this change the oldPagingEpoxyController
has been deprecated, and the wiki is updated. -
New Add databinding option to not auto apply DoNotHash (#539)
-
Fixed Fix AsyncEpoxyController constructor to correctly use boolean setting (#537)
-
Fixed
app_name
is removed from module manifests (#543 Thanks @kettsun0123!)
- New Add support for setting the Padding via resource or directly in dp (airbnb#528 Thanks to pwillmann!)
- Fixed Strip kotlin metadata annotation from generated classes (airbnb#523)
- Fixed Reflect the annotations declared in constructor params (airbnb#519 Thanks to Shaishav Gandhi!)
- New
EpoxyAsyncUtil
andAsyncEpoxyController
make it easier to use Epoxy's async behavior out of the box - New Epoxy's background diffing posts messages back to the main thread asynchronously so they are not blocked by waiting for vsync
- New Add
AsyncEpoxyController
for easy access to async support. Change background diffing to post asynchronously to the main thread (airbnb#509)
- Fix Kotlin lambdas can be used in model constructors (airbnb#501)
- New Added function to check whether a model build is pending (airbnb#506)
- Fix Update EpoxyController async model building so threading works with tests (airbnb#504)
-
New EpoxyController now supports asynchronous model building and diffing by allowing you to provide a custom Handler to run these tasks. See the wiki for more details.
-
New The
EpoxyController#addModelBuildListener
method was added to support listening for when model changes are dispatched to the recyclerview.
-
New Added kotlin sample code for building models. Updated wiki with info (https://github.com/airbnb/epoxy/wiki/Kotlin-Model-Examples)
-
Fix Generated kotlin extension functions now work with Models with type variables (airbnb#478)
-
Fix Backup is not enabled in manifest now (airbnb#481)
-
Fix Click listener setter on generated model has correct nullability annotation (airbnb#458)
-
Fix Avoid kotlin crash using toString on lambdas (airbnb#482)
-
Fix If EpoxyModelGroup has annotations the generated class now calls super methods correctly. (airbnb#483)
- New Experimental support for creating Epoxy models from arbitrary data formats (#450)
- Fix Reduce memory usage in model groups and differ (#433)
- Fix Support for wildcards in private epoxy attributes (#451)
- Fix Generated Kotlin Extensions Don't Adhere to Constructor Nullability (#449)
- Fix Infinite loop in annotation processor (#447)
-
Breaking Several updates to the Paging Library integration were made (airbnb#421)
- The
PagingEpoxyController
class had the methodssetNumPagesToLoad
andsetPageSizeHint
removed - Page hints are now taken from the
Config
object off of the PagedList. See thesetConfig
javadoc for information on how config values are used: https://github.com/airbnb/epoxy/blob/master/epoxy-paging/src/main/java/com/airbnb/epoxy/paging/PagingEpoxyController.java#L220 - Several tweaks were made to how the page size and prefetch distance affect model rebuilding. Take some time to make sure your config values make sense and produce good results for your use case
- A crash on empty list was fixed (airbnb#420)
- The
-
New The Paris library is now officially supported to allow dynamically styling RecyclerView items though Epoxy models. See the wiki for more info.
- Fix Make databinding work with Android Studio 3.1 (airbnb#418)
- Make
EpoxyController#isBuildingModels
public (airbnb#406
- Improved Allow the
Model_
class suffix for models generated via@ModelView
to be customized (airbnb#402 Big thanks to geralt-encore!)
-
Improved Global defaults for EpoxyController settings. Set duplicate filtering and exception handlers for all your controllers. (airbnb#394)
-
Improved Add
@NonNull
annotations in EpoxyModel for better Kotlin interop -
Fixed Model click listeners now rebind correctly on partial model diffs (airbnb#393)
-
Fixed Update Android Paging library to fix placeholder support (Thanks @wkranich! airbnb#360)
-
Fixed Improve error message for inaccessible private fields (airbnb#388)
-
New Use
@ModelProp
directly on fields to avoid creating a setter (airbnb#343) -
New Set EpoxyRecyclerView item spacing via xml attribute (airbnb#364)
-
New More flexibility over setting Carousel padding values (airbnb#369)
-
New Allow custom EpoxyModelGroup root view (airbnb#370)
-
Fixed Public visibility settings of the Carousel snap helper settings (airbnb#356)
-
Fixed Add more nullability annotations to better support Kotlin
-
Fixed Saving view state now works better (airbnb#367)
- Fixed When a model changed and a partial update was bound to an existing view the wrong values could be set for prop groups (airbnb#347)
- Fixed Using
EpoxyDataBindingPattern
could result in the wrong package being used for the BR class in generated models.
Several fixes:
-
New If a
@ModelView
generated model has a custom base class the generated model will now inherit constructors from the base class (airbnb#315) -
New Use the
EpoxyDataBindingPattern
annotation to specify a naming pattern for databinding layouts. This removes the need to declare every databinding layout explicitly (Wiki - airbnb#319) -
New If a view with
@ModelView
implements an interface then the generated model will implement a similar interface, enabling polymorphism with models. Wiki -
Improvement
PagingEpoxyController
now has getters to access the underlying data lists (Thanks to @pcqpcq - airbnb#317) -
Improvement
EpoxyModelGroup
now supports partial rebinds (airbnb#316)
-
Improvement If a
OnModelClickListener
is used it will not be called if a view is clicked while it is being removed or otherwise has no position (airbnb#293 - Thanks @niccorder!) -
New
EpoxyRecyclerView
andCarousel
provide out of the box integration with Epoxy along with other enhancements over regular RecyclerView (https://github.com/airbnb/epoxy/wiki/EpoxyRecyclerView) -
New
EpoxyPagingController
provides integration with the Android Paging architecture component as well as normal, large lists of items (https://github.com/airbnb/epoxy/wiki/Large-Data-Sets)
- Improvement Disable kotlin extension function generation with the annotation processor flag
disableEpoxyKotlinExtensionGeneration
(airbnb#309) - Fix If a model has a non empty constructor the generated extension function will now use it.
- Fixed The wrong import was being generated for models using a view holder in 2.5.0 (airbnb#294)
- Fixed Fix generated code failing to compile if a subclass of View.OnClickListener is used as an attribute (airbnb#296)
- New Feature Epoxy now generates a Kotlin DSL to use when building models in your EpoxyController! See the wiki for details
- New Feature You can use the
autoLayout
parameter in@ModelView
instead of needing to create a layout resource fordefaultLayout
. Epoxy will then create your view programmatically (airbnb#282).
Breaking
- The
onSwipeProgressChanged
callback inEpoxyTouchHelper
had aCanvas
parameter added (airbnb#280). You will need to update any of your usages to add this. Sorry for the inconvenience; this will hopefully help you add better swipe animations.
-
Improvement If you are setting options on a @ModelProp and have no other annotation parameters you can now omit the explicit
options =
param name (airbnb#268) -
Improvement If you are using
@TextProp
you can now specify a default string via a string resource (airbnb#269) -
Fixed EpoxyModelGroup was not binding model click listeners correctly (airbnb#267)
-
Fixed A model created with @ModelView could fail to compile if it had nullable prop overloads (airbnb#274)
A model created with @ModelView with a click listener had the wrong setter name for the model click listener overload (airbnb#275)
If you were setting this you will need to update the setter name. If you were setting the click listener to null you may now have to cast it.
- New An
AfterPropsSet
annotation for use in@ModelView
classes. This allows initialization work to be done after all properties are bound from the model. (airbnb#242) - New Annotations
TextProp
andCallbackProp
as convenient replacements forModelProp
. (airbnb#260) - New Easy support for dragging and swiping via the
EpoxyTouchHelper
class. https://github.com/airbnb/epoxy/wiki/Touch-Support - Change Added the method
getRootView
to the view holder class inEpoxyModelGroup
and made the bind methods onEpoxyModelGroup
non final. This allows access to the root view of the group. - Change Generated models will now inherit class annotations from the base class (airbnb#255 Thanks geralt-encore!)
-
Main Feature Models can now be completely generated from a custom view via annotations on the view. This should completely remove the overhead of creating a model manually in many cases! For more info, see the wiki
-
New Lowered the minimum SDK from 16 to 14.
-
New Models that have a
View.OnLongClickListener
as an EpoxyAttribute will now have an overloaded setter on the generated model that allows you to set a long click listener that will return the model, view, and adapter position. This is very similar to theView.OnClickListener
support added in 2.0.0, but for long click listeners. Upgrade Note If you were setting a long click listener value to null anywhere you will need to now cast that toView.OnLongClickListener
because of the new overloaded method. -
New
id
overload on EpoxyModel to define a model id with multiple strings -
New Option in
EpoxyAttribute
to not include the attribute in the generatedtoString
method (Thanks to @geralt-encore!) -
New @AutoModel models are now inherited from usages in super classes (Thanks to @geralt-encore!)
-
Fixed Generated getters could recursively call themselves (Thanks to @geralt-encore!)
- New: Support for Android Data Binding! Epoxy will now generate an EpoxyModel directly from a Data Binding xml layout, and handle all data binding details automatically. Thanks to @geralt-encore for helping with this! See more details in the wiki.
- New: Support for Litho. Epoxy will now generate an EpoxyModel for Litho Layout Specs. See more details in the wiki.
- New: Support for implicitly adding AutoModels to an EpoxyController, this let's you drop the extra
.addTo(this)
line. More details and instructions here
- New: The
EpoxyController
class helps you manage even models better. This should be used instead of the originalEpoxyAdapter
in most places. Read more aboutEpoxyController
in the wiki. - Change: In the new EpoxyController, the diffing algorithm uses both
equals
andhashCode
on each model to check for changes. This is a change from the EpoxyAdapter where onlyhashCode
was used. Generated models have both hashCode and equals implemented properly already, but if you have any custom hashCode implementations in your models make sure you have equals implemented as well. - New: Models that have a
View.OnClickListener
as an EpoxyAttribute will now have an overloaded setter on the generated model that allows you to set a click listener that will return the model, view, and adapter position. Upgrade Note If you were setting a click listener value to null anywhere you will need to now cast that toView.OnClickListener
because of the new overloaded method. - New: Attach an onBind/onUnbind listener directly to a model instead of overriding the onModelBound method. Generated models will have methods created to set this listener and handle the callback for you.
- New: Support for creating models in Kotlin (Thanks to @geralt-encore! airbnb#144)
- New:
EpoxyModelWithView
supports creating a View programmatically instead of inflating from XML. - New:
EpoxyModelGroup
supports grouping models together in arbitrary formations. - New: Instead of setting attribute options like
@EpoxyAttribute(hash = false)
you should now do@EpoxyAttribute(DoNotHash)
. You can also set other options like that. - New: Annotation processor options can now be set via gradle instead of with
PackageEpoxyConfig
- New: In an EpoxyController, if a model with the same id changes state Epoxy will include its previous state as a payload in the change notification. The new model will have its
bind(view, previouslyBoundModel)
method called so it can compare what changed since the previous model, and so it can update the view with only the data that changed.
- New: Models inherit layouts specified in superclass
@EpoxyModelClass
annotations #119 - New: Support module configuration options #124
- New: Support layout resource annotations in library projects (airbnb#116)
- Allow the default layout resource to be specified in the EpoxyModelClass class annotation (#109) (#111)
- Allow the
createNewHolder
method to be omitted and generated automatically (#105) - Generate a subclass for abstract model classes if the EpoxyModelClass annotation is present (#105)
- Allow strings as model ids (#107)
- Add instructions to readme for avoiding memory leaks (#106)
- Add model callbacks for view attached/detached from window, and onFailedToRecycleView (#104)
- Improve documentation on model unbind behavior (#103)
- Fix generated methods from super classes that have var args (#100)
- Remove apt dependency (#95)
- Add
removeAllModels
method to EpoxyAdapter (#94) - Use actual param names when generating methods from super classes (#85)
- Fixes models being used in separate modules
- Generates a
reset()
method on each model to reset annotated fields to their defaults. - Changes
@EpoxyAttribute(hash = false)
to still differentiate between null and non null values in the hashcode implementation - Adds a
notifyModelChanged
method to EpoxyAdapter that allows a payload to be specified - Generates a
toString()
method on all generated model classes that includes the values of all annotated fields.
- Optimizations to the diffing algorithm
- Setters on generated classes are not created if an @EpoxyAttribute field is marked as
final
- Adds @EpoxyModelClass annotation to force a model to have a generated class, even if it doesn't have any @EpoxyAttribute fields
- Fix to not generate methods for package private @EpoxyAttribute fields that are in a different package from the generated class
- Have generated classes duplicate any super methods that have the model as the return type to help with chaining
- Add support for using the view holder pattern with models. See the readme for more information.
- Throw an exception if
EpoxyAdapter#notifyDataSetChanged()
is called when diffing is enabled. It doesn't make sense to allow this alongside diffing, and calling this is most likely to be an accidental mixup withnotifyModelsChanged()
. - Some performance improvements with the diffing algorithm.
- Change signature of
EpoxyAdapter#onModelBound
to include the model position - Fix EpoxyModel hashcode to include the layout specified by
getDefaultLayout
- Enforce that the id of an
EpoxyModel
cannot change once it has been added to the adapter - Add optional hash parameter to the
EpoxyAttribute
annotation to exclude a field from being included in the generated hashcode method.
- Initial release