Skip to content

Commit

Permalink
Allow string ids (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
elihart authored Feb 3, 2017
1 parent c224a3b commit cbfd18b
Show file tree
Hide file tree
Showing 19 changed files with 304 additions and 0 deletions.
70 changes: 70 additions & 0 deletions epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,76 @@ public EpoxyModel<T> id(long id) {
return this;
}

/**
* Use a string as the model id. Useful for models that don't clearly map to a numerical id. This
* is preferable to using {@link String#hashCode()} because that is a 32 bit hash and this is a 64
* bit hash, giving better spread and less chance of collision with other ids.
* <p>
* Since this uses a hashcode method to convert the String to a long there is a very small
* chance that you may have a collision with another id. Assuming an even spread of hashcodes, and
* several hundred models in the adapter, there would be roughly 1 in 100 trillion chance of a
* collision. (http://preshing.com/20110504/hash-collision-probabilities/)
*
* @see EpoxyModel#hashString64Bit(CharSequence)
*/
public EpoxyModel<T> id(CharSequence key) {
id(hashString64Bit(key));
return this;
}

/**
* Set an id that is namespaced with a string. This is useful when you need to show models of
* multiple types, side by side and don't want to risk id collisions.
* <p>
* Since this uses a hashcode method to convert the String to a long there is a very small chance
* that you may have a collision with another id. Assuming an even spread of hashcodes, and
* several hundred models in the adapter, there would be roughly 1 in 100 trillion chance of a
* collision. (http://preshing.com/20110504/hash-collision-probabilities/)
*
* @see EpoxyModel#hashString64Bit(CharSequence)
* @see EpoxyModel#hashLong64Bit(long)
*/
public EpoxyModel<T> id(CharSequence key, long id) {
long result = hashString64Bit(key);
result = 31 * result + hashLong64Bit(id);
id(result);
return this;
}

/**
* Hash a long into 64 bits instead of the normal 32. This uses a xor shift implementation to
* attempt psuedo randomness so object ids have an even spread for less chance of collisions.
* <p>
* From http://stackoverflow.com/a/11554034
* <p>
* http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
*/
private static long hashLong64Bit(long value) {
value ^= (value << 21);
value ^= (value >>> 35);
value ^= (value << 4);
return value;
}

/**
* Hash a string into 64 bits instead of the normal 32. This allows us to better use strings as a
* model id with less chance of collisions. This uses the FNV-1a algorithm for a good mix of speed
* and distribution.
* <p>
* Performance comparisons found at http://stackoverflow.com/a/1660613
* <p>
* Hash implementation from http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-1a
*/
private static long hashString64Bit(CharSequence str) {
long result = 0xcbf29ce484222325L;
final int len = str.length();
for (int i = 0; i < len; i++) {
result ^= str.charAt(i);
result *= 0x100000001b3L;
}
return result;
}

@LayoutRes
protected abstract int getDefaultLayout();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand Down Expand Up @@ -28,6 +29,18 @@ public BasicModelWithAttribute_ id(long id) {
return this;
}

@Override
public BasicModelWithAttribute_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public BasicModelWithAttribute_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public BasicModelWithAttribute_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand Down Expand Up @@ -40,6 +41,18 @@ public ModelReturningClassTypeWithVarargs_ id(long id) {
return this;
}

@Override
public ModelReturningClassTypeWithVarargs_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelReturningClassTypeWithVarargs_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelReturningClassTypeWithVarargs_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand Down Expand Up @@ -47,6 +48,18 @@ public ModelReturningClassType_ id(long id) {
return this;
}

@Override
public ModelReturningClassType_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelReturningClassType_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelReturningClassType_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.support.annotation.LayoutRes;
import java.lang.Boolean;
import java.lang.Byte;
import java.lang.CharSequence;
import java.lang.Character;
import java.lang.Double;
import java.lang.Float;
Expand Down Expand Up @@ -217,6 +218,18 @@ public ModelWithAllFieldTypes_ id(long id) {
return this;
}

@Override
public ModelWithAllFieldTypes_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithAllFieldTypes_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithAllFieldTypes_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand All @@ -27,6 +28,18 @@ public int superValue() {
return this;
}

@Override
public ModelWithAnnotatedClassAndSuperAttributes$SubModelWithAnnotatedClassAndSuperAttributes_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithAnnotatedClassAndSuperAttributes$SubModelWithAnnotatedClassAndSuperAttributes_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithAnnotatedClassAndSuperAttributes$SubModelWithAnnotatedClassAndSuperAttributes_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand All @@ -27,6 +28,18 @@ public ModelWithAnnotatedClassAndSuperAttributes_ id(long id) {
return this;
}

@Override
public ModelWithAnnotatedClassAndSuperAttributes_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithAnnotatedClassAndSuperAttributes_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithAnnotatedClassAndSuperAttributes_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand All @@ -19,6 +20,18 @@ public ModelWithAnnotatedClass_ id(long id) {
return this;
}

@Override
public ModelWithAnnotatedClass_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithAnnotatedClass_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithAnnotatedClass_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
13 changes: 13 additions & 0 deletions epoxy-processortest/src/test/resources/ModelWithConstructors_.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand Down Expand Up @@ -35,6 +36,18 @@ public ModelWithConstructors_ id(long id) {
return this;
}

@Override
public ModelWithConstructors_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithConstructors_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithConstructors_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand Down Expand Up @@ -29,6 +30,18 @@ public ModelWithFieldAnnotation_ id(long id) {
return this;
}

@Override
public ModelWithFieldAnnotation_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithFieldAnnotation_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithFieldAnnotation_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
13 changes: 13 additions & 0 deletions epoxy-processortest/src/test/resources/ModelWithFinalField_.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand All @@ -22,6 +23,18 @@ public ModelWithFinalField_ id(long id) {
return this;
}

@Override
public ModelWithFinalField_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithFinalField_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithFinalField_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
13 changes: 13 additions & 0 deletions epoxy-processortest/src/test/resources/ModelWithIntDef_.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.airbnb.epoxy.models;

import android.support.annotation.LayoutRes;
import java.lang.CharSequence;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
Expand Down Expand Up @@ -28,6 +29,18 @@ public ModelWithIntDef_ id(long id) {
return this;
}

@Override
public ModelWithIntDef_ id(CharSequence key) {
super.id(key);
return this;
}

@Override
public ModelWithIntDef_ id(CharSequence key, long id) {
super.id(key, id);
return this;
}

@Override
public ModelWithIntDef_ layout(@LayoutRes int arg0) {
super.layout(arg0);
Expand Down
Loading

0 comments on commit cbfd18b

Please sign in to comment.