Data Binding click listener is included in generated model's equals and hashCode
See original GitHub issueI’m using Epoxy version 3.3.0 with databinding.
My model has a click listener which is Kotlin Function1<String, Unit>
.
In the documentation it mentions that DoNotHash
is enabled by default for any variable whose type does not implement equals and hashcode.
According to my understanding DoNotHash
should be applied to this click listener, but after inspecting the generated code, I see that that’s not the case and in fact the listener is part of the generated equals and hashCode.
Here’s a snippet of my viewholder layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.codepond.commitbrowser.commitlist.CommitListActivity">
<data>
<import type="kotlin.jvm.functions.Function1"/>
<import type="kotlin.Unit"/>
<variable name="click" type="Function1<String, Unit>"/>
<variable name="commitInfo" type="org.codepond.commitbrowser.commitlist.CommitInfo"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/commit_list_item"
android:layout_width="match_parent"
android:layout_height="@dimen/three_line_list_item_height"
android:background="?selectableItemBackground"
android:onClick="@{() -> click.invoke(commitInfo.sha)}"
android:clickable="true"
android:focusable="true">
And here’s a snippet of the generated model code:
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof CommitInfoBindingModel_)) {
return false;
}
if (!super.equals(o)) {
return false;
}
CommitInfoBindingModel_ that = (CommitInfoBindingModel_) o;
if (((onModelBoundListener_epoxyGeneratedModel == null) != (that.onModelBoundListener_epoxyGeneratedModel == null))) {
return false;
}
if (((onModelUnboundListener_epoxyGeneratedModel == null) != (that.onModelUnboundListener_epoxyGeneratedModel == null))) {
return false;
}
if (((onModelVisibilityStateChangedListener_epoxyGeneratedModel == null) != (that.onModelVisibilityStateChangedListener_epoxyGeneratedModel == null))) {
return false;
}
if (((onModelVisibilityChangedListener_epoxyGeneratedModel == null) != (that.onModelVisibilityChangedListener_epoxyGeneratedModel == null))) {
return false;
}
if ((click != null ? !click.equals(that.click) : that.click != null)) {
return false;
}
if ((commitInfo != null ? !commitInfo.equals(that.commitInfo) : that.commitInfo != null)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (onModelBoundListener_epoxyGeneratedModel != null ? 1 : 0);
result = 31 * result + (onModelUnboundListener_epoxyGeneratedModel != null ? 1 : 0);
result = 31 * result + (onModelVisibilityStateChangedListener_epoxyGeneratedModel != null ? 1 : 0);
result = 31 * result + (onModelVisibilityChangedListener_epoxyGeneratedModel != null ? 1 : 0);
result = 31 * result + (click != null ? click.hashCode() : 0);
result = 31 * result + (commitInfo != null ? commitInfo.hashCode() : 0);
return result;
}
As you can see above, equals and hashCode include click
.
Please note that I also tried with a standard interface
such as
interface OnClickListener {
fun onClick(sha: String)
}
which I then used in the viewholder layout XML, yet the generated code still included it in equals and hashCode.
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (2 by maintainers)
I was wrong earlier - the wiki is right, and this is correct ->
DoNotHash is enabled by default for any variable whose type does not implement equals and hashcode.
I was on vacation for a few weeks when I replied and didn’t have a my laptop.
You can see the code that implements this at https://github.com/airbnb/epoxy/blob/7523c9ec2a4ff9daf0aada9eaab407ba2c1f737c/epoxy-processor/src/main/java/com/airbnb/epoxy/DataBindingAttributeInfo.kt#L17
I’m not sure why it is excluding Function1 - the processor code needs equals and hashcode to only exist on the base
Object
, so perhaps the kotlin implementation also defines those functions.If you are interested in pursuing this can you open a new issue for
Support Kotlin Function1 in Databinding DoNotHash
And if anybody wants to fix it it may be as simple as adding it to the whitelist: https://github.com/airbnb/epoxy/blob/ed916a0ea64beb7f28d18d2b1786e33aacbb1975/epoxy-processor/src/main/java/com/airbnb/epoxy/HashCodeValidator.java#L31
@elihart I see you closed the issue. I think it would be a good idea to at least update the documentation to clarify this restriction.