From c182933aa63873ac72dd34f0383a4b121fcf525a Mon Sep 17 00:00:00 2001 From: Eli Hart Date: Thu, 18 Aug 2016 20:27:01 -0700 Subject: [PATCH] Add checkstyle --- build.gradle | 60 ++++++--- checkstyle.xml | 117 ++++++++++++++++++ .../java/com/airbnb/epoxy/DiffHelper.java | 104 ++++++++++------ .../java/com/airbnb/epoxy/EpoxyAdapter.java | 62 ++++++---- .../com/airbnb/epoxy/EpoxyItemAnimator.java | 19 --- .../com/airbnb/epoxy/EpoxyViewHolder.java | 10 +- .../com/airbnb/epoxy/HiddenEpoxyModel.java | 5 +- .../java/com/airbnb/epoxy/ModelState.java | 44 ++++--- .../com/airbnb/epoxy/SimpleEpoxyModel.java | 6 +- .../main/java/com/airbnb/epoxy/UpdateOp.java | 22 ++-- .../com/airbnb/epoxy/ViewHolderState.java | 30 +++-- epoxy-model/build.gradle | 5 + .../java/com/airbnb/epoxy/EpoxyAttribute.java | 2 +- .../java/com/airbnb/epoxy/EpoxyModel.java | 12 +- epoxy-processor/build.gradle | 5 + .../java/com/airbnb/epoxy/AttributeInfo.java | 24 ++-- .../com/airbnb/epoxy/ClassToGenerateInfo.java | 25 ++-- .../java/com/airbnb/epoxy/EpoxyProcessor.java | 26 ++-- .../airbnb/epoxy/EpoxyProcessorException.java | 2 +- .../com/airbnb/epoxy/EpoxyProcessorTest.java | 2 +- .../java/com/airbnb/epoxy/MainActivity.java | 2 +- .../epoxy/ModelWithSuperAttributes.java | 15 --- .../java/com/airbnb/epoxy/NumberModel.java | 33 ----- 23 files changed, 389 insertions(+), 243 deletions(-) create mode 100644 checkstyle.xml delete mode 100755 epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyItemAnimator.java delete mode 100755 epoxy-sample/src/main/java/com/airbnb/epoxy/ModelWithSuperAttributes.java delete mode 100755 epoxy-sample/src/main/java/com/airbnb/epoxy/NumberModel.java diff --git a/build.gradle b/build.gradle index 0555ff4605..cb2eea74e9 100755 --- a/build.gradle +++ b/build.gradle @@ -1,48 +1,68 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - repositories { - maven { url 'http://airbnb-maven-proxy.d.musta.ch/nexus/content/groups/public' } - } - dependencies { - classpath 'com.android.tools.build:gradle:2.2.0-beta1' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' - classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1' - } + repositories { + maven { url 'http://airbnb-maven-proxy.d.musta.ch/nexus/content/groups/public' } + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.0-beta2' + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' + classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1' + } } allprojects { - repositories { - maven { url 'http://airbnb-maven-proxy.d.musta.ch/nexus/content/groups/public' } + repositories { + maven { url 'http://airbnb-maven-proxy.d.musta.ch/nexus/content/groups/public' } + } +} + +subprojects { project -> + apply plugin: 'checkstyle' + + task checkstyle(type: Checkstyle) { + configFile rootProject.file('checkstyle.xml') + source 'src/main/java' + ignoreFailures false + showViolations true + include '**/*.java' + + classpath = files() + } + + afterEvaluate { + if (project.tasks.findByName('check')) { + check.dependsOn('checkstyle') } + } } def isCi() { - project.hasProperty('CI') && CI.equals('true') + project.hasProperty('CI') && CI.equals('true') } def isReleaseBuild() { - return VERSION_NAME.contains("SNAPSHOT") == false + return VERSION_NAME.contains("SNAPSHOT") == false } def getReleaseRepositoryUrl() { - return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL - : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL + : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" } def getSnapshotRepositoryUrl() { - return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL - : "https://oss.sonatype.org/content/repositories/snapshots/" + return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL + : "https://oss.sonatype.org/content/repositories/snapshots/" } def getRepositoryUsername() { - return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" + return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" } def getRepositoryPassword() { - return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" + return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" } task wrapper(type: Wrapper) { - gradleVersion = '2.14' - distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" + gradleVersion = '2.14' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" } diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000000..9d4c11100a --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java index b331244468..3174538e6b 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/DiffHelper.java @@ -16,7 +16,8 @@ class DiffHelper { private ArrayList oldStateList = new ArrayList<>(); - // Using a HashMap instead of a LongSparseArray to have faster look up times at the expense of memory + // Using a HashMap instead of a LongSparseArray to + // have faster look up times at the expense of memory private Map oldStateMap = new HashMap<>(); private ArrayList currentStateList = new ArrayList<>(); private Map currentStateMap = new HashMap<>(); @@ -75,7 +76,8 @@ public void onItemRangeRemoved(int positionStart, int itemCount) { return; } - List modelsToRemove = currentStateList.subList(positionStart, positionStart + itemCount); + List modelsToRemove = + currentStateList.subList(positionStart, positionStart + itemCount); for (ModelState model : modelsToRemove) { currentStateMap.remove(model.id); ModelState.release(model); @@ -97,8 +99,8 @@ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { } if (itemCount != 1) { - throw new IllegalArgumentException("Moving more than 1 item at a time is not " + - "supported. Number of items moved: " + itemCount); + throw new IllegalArgumentException("Moving more than 1 item at a time is not " + + "supported. Number of items moved: " + itemCount); } ModelState model = currentStateList.remove(fromPosition); @@ -120,15 +122,18 @@ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { }; /** - * Set the current list of models. The diff callbacks will be notified of the changes between the current list and the last list that was set. + * Set the current list of models. The diff callbacks will be notified of the changes between the + * current list and the last list that was set. */ public void notifyModelChanges() { - // We use a list of the models as well as a map by their id, so we can easily find them by both position and id + // We use a list of the models as well as a map by their id, + // so we can easily find them by both position and id swapCurrentStateToOld(); buildCurrentState(); List diff = buildDiff(); - // Send out the proper notify calls for the diff. We remove our observer first so that we don't react to our own notify calls + // Send out the proper notify calls for the diff. We remove our + // observer first so that we don't react to our own notify calls adapter.unregisterAdapterDataObserver(observer); notifyChanges(diff); adapter.registerAdapterDataObserver(observer); @@ -139,16 +144,16 @@ public void notifyModelChanges() { private void notifyChanges(List diff) { for (UpdateOp op : diff) { switch (op.type) { - case UpdateOp.Add: + case UpdateOp.ADD: adapter.notifyItemRangeInserted(op.positionStart, op.itemCount); break; - case UpdateOp.Move: + case UpdateOp.MOVE: adapter.notifyItemMoved(op.positionStart, op.itemCount); break; - case UpdateOp.Remove: + case UpdateOp.REMOVE: adapter.notifyItemRangeRemoved(op.positionStart, op.itemCount); break; - case UpdateOp.Update: + case UpdateOp.UPDATE: adapter.notifyItemRangeChanged(op.positionStart, op.itemCount); break; default: @@ -175,7 +180,8 @@ private ModelState createStateForPosition(int position) { ModelState previousValue = currentStateMap.put(state.id, state); if (previousValue != null) { - throw new IllegalStateException("Duplicate ID for model: " + state + " Original: " + previousValue); + throw new IllegalStateException( + "Duplicate ID for model: " + state + " Original: " + previousValue); } return state; @@ -193,14 +199,16 @@ private void swapCurrentStateToOld() { } /** - * Create a list of operations that define the difference between {@link #oldStateList} and {@link #currentStateList}. + * Create a list of operations that define the difference between {@link #oldStateList} and {@link + * #currentStateList}. */ private List buildDiff() { List result = new ArrayList<>(); // The general approach is to first search for removals, then additions, and lastly changes. // Focusing on one type of operation at a time makes it easy to coalesce batch changes. - // When we identify an operation and add it to the result list we update the postions of items in the oldStateList to reflect + // When we identify an operation and add it to the + // result list we update the postions of items in the oldStateList to reflect // the change, this way subsequent operations will use the correct, updated positions. collectRemovals(result); collectInsertions(result); @@ -211,8 +219,9 @@ private List buildDiff() { } /** - * Find all removal operations and add them to the result list. The general strategy here is to walk through the {@link #oldStateList} and check for - * items that don't exist in the new list. Walking through it in order makes it easy to batch adjacent removals. + * Find all removal operations and add them to the result list. The general strategy here is to + * walk through the {@link #oldStateList} and check for items that don't exist in the new list. + * Walking through it in order makes it easy to batch adjacent removals. */ private void collectRemovals(List result) { int removalCount = 0; @@ -222,7 +231,8 @@ private void collectRemovals(List result) { // so that future operations will reference the correct position state.position -= removalCount; - // This is our first time going through the list, so we look up the item with the matching id in the new + // This is our first time going through the list, so we + // look up the item with the matching id in the new // list and hold a reference to it so that we can access it quickly in the future state.pair = currentStateMap.get(state.id); if (state.pair != null) { @@ -237,7 +247,7 @@ private void collectRemovals(List result) { if (lastRemoval != null) { result.add(lastRemoval); } - lastRemoval = UpdateOp.instance(UpdateOp.Remove, indexToRemove); + lastRemoval = UpdateOp.instance(UpdateOp.REMOVE, indexToRemove); } removalCount++; } @@ -248,8 +258,9 @@ private void collectRemovals(List result) { } /** - * Find all insertion operations and add them to the result list. The general strategy here is to walk through the {@link #currentStateList} and - * check for items that don't exist in the old list. Walking through it in order makes it easy to batch adjacent insertions. + * Find all insertion operations and add them to the result list. The general strategy here is to + * walk through the {@link #currentStateList} and check for items that don't exist in the old + * list. Walking through it in order makes it easy to batch adjacent insertions. */ private void collectInsertions(List result) { UpdateOp lastInsertion = null; @@ -267,13 +278,14 @@ private void collectInsertions(List result) { } // If the item to insert is adjacent to our last insertion operation we can batch them - if (lastInsertion != null && (lastInsertion.positionStart + lastInsertion.itemCount) == itemToInsert.position) { + if (lastInsertion != null + && (lastInsertion.positionStart + lastInsertion.itemCount) == itemToInsert.position) { lastInsertion.itemCount++; } else { if (lastInsertion != null) { result.add(lastInsertion); } - lastInsertion = UpdateOp.instance(UpdateOp.Add, itemToInsert.position); + lastInsertion = UpdateOp.instance(UpdateOp.ADD, itemToInsert.position); } insertionCount++; @@ -295,13 +307,14 @@ private void collectChanges(List result) { } if (newItem.pair.hashCode != newItem.hashCode) { - if (lastUpdateOp != null && (lastUpdateOp.positionStart + lastUpdateOp.itemCount) == newItem.position) { + if (lastUpdateOp != null + && (lastUpdateOp.positionStart + lastUpdateOp.itemCount) == newItem.position) { lastUpdateOp.itemCount++; } else { if (lastUpdateOp != null) { result.add(lastUpdateOp); } - lastUpdateOp = UpdateOp.instance(UpdateOp.Update, newItem.position); + lastUpdateOp = UpdateOp.instance(UpdateOp.UPDATE, newItem.position); } } } @@ -319,8 +332,10 @@ private void collectMoves(List result) { Iterator oldItemIterator = oldStateList.iterator(); ModelState nextOldItem = null; - // We have to be careful to update all item positions in the list when we do a MOVE. This adds some complexity. - // To do this we keep track of all moves and apply them to an item when we need the up to date position + // We have to be careful to update all item positions in the list when we + // do a MOVE. This adds some complexity. + // To do this we keep track of all moves and apply them to an item when we + // need the up to date position List moveOps = new ArrayList<>(); for (ModelState newItem : currentStateList) { @@ -328,23 +343,31 @@ private void collectMoves(List result) { continue; } - // We could iterate through only the new list and move each item that is out of place, however in cases such as moving the first item - // to the end that strategy would do many moves to move all items up one, instead of doing one move to move the first item to the end. - // To avoid this we compare the old item to the new item at each index and move the one that is farthest from its correct position. - // We only move on from a new item once its pair is placed in the correct spot. Since we move from start to end, all new items we've - // already iterated through are guaranteed to have their pair be already in the righ spot, which won't be affected by future MOVEs. + // We could iterate through only the new list and move each + // item that is out of place, however in cases such as moving the first item + // to the end that strategy would do many moves to move all + // items up one, instead of doing one move to move the first item to the end. + // To avoid this we compare the old item to the new item at + // each index and move the one that is farthest from its correct position. + // We only move on from a new item once its pair is placed in + // the correct spot. Since we move from start to end, all new items we've + // already iterated through are guaranteed to have their pair + // be already in the righ spot, which won't be affected by future MOVEs. if (nextOldItem == null) { nextOldItem = getNextItemWithPair(oldItemIterator); - // We've already iterated through all old items and moved each item once. However, subsequent moves may have shifted an item out of - // its correct space once it was already moved. We finish iterating through all the new items to ensure everything is still correct + // We've already iterated through all old items and moved each + // item once. However, subsequent moves may have shifted an item out of + // its correct space once it was already moved. We finish + // iterating through all the new items to ensure everything is still correct if (nextOldItem == null) { nextOldItem = newItem.pair; } } while (nextOldItem != null) { - // Make sure the positions are updated to the latest move operations before we calculate the next move + // Make sure the positions are updated to the latest + // move operations before we calculate the next move updateItemPosition(newItem.pair, moveOps); updateItemPosition(nextOldItem, moveOps); @@ -364,7 +387,8 @@ private void collectMoves(List result) { } if (oldItemDistance > newItemDistance) { - UpdateOp moveOp = UpdateOp.instance(UpdateOp.Move, nextOldItem.position, nextOldItem.pair.position); + UpdateOp moveOp = + UpdateOp.instance(UpdateOp.MOVE, nextOldItem.position, nextOldItem.pair.position); result.add(moveOp); moveOps.add(moveOp); @@ -373,7 +397,8 @@ private void collectMoves(List result) { nextOldItem = getNextItemWithPair(oldItemIterator); } else { - UpdateOp moveOp = UpdateOp.instance(UpdateOp.Move, newItem.pair.position, newItem.position); + UpdateOp moveOp = + UpdateOp.instance(UpdateOp.MOVE, newItem.pair.position, newItem.position); result.add(moveOp); moveOps.add(moveOp); @@ -386,8 +411,9 @@ private void collectMoves(List result) { } /** - * Apply the movement operations to the given item to update its position. Only applies the operations that have not been applied yet, and stores - * how many operations have been applied so we know which ones to apply next time. + * Apply the movement operations to the given item to update its position. Only applies the + * operations that have not been applied yet, and stores how many operations have been applied so + * we know which ones to apply next time. */ private void updateItemPosition(ModelState item, List moveOps) { int size = moveOps.size(); @@ -424,4 +450,4 @@ private ModelState getNextItemWithPair(Iterator iterator) { return nextItem; } -} \ No newline at end of file +} diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyAdapter.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyAdapter.java index 9db40aaf2f..84a9023ec5 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyAdapter.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyAdapter.java @@ -12,25 +12,28 @@ import java.util.List; /** - * Allows you to easily combine different view types in the same adapter, and handles view holder creation, binding, and ids for you. Subclasses just - * need to add their desired {@link EpoxyModel} objects and the rest is done automatically. + * Allows you to easily combine different view types in the same adapter, and handles view holder + * creation, binding, and ids for you. Subclasses just need to add their desired {@link EpoxyModel} + * objects and the rest is done automatically. *

- * {@link android.support.v7.widget.RecyclerView.Adapter#setHasStableIds(boolean)} is set to true by default, since {@link EpoxyModel} makes it easy to - * support unique ids. If you don't want to support this then disable it in your base class (not recommended). + * {@link android.support.v7.widget.RecyclerView.Adapter#setHasStableIds(boolean)} is set to true by + * default, since {@link EpoxyModel} makes it easy to support unique ids. If you don't want to + * support this then disable it in your base class (not recommended). */ @SuppressWarnings("WeakerAccess") public abstract class EpoxyAdapter extends RecyclerView.Adapter { private static final String SAVED_STATE_ARG_VIEW_HOLDERS = "saved_state_view_holders"; /** - * Subclasses should modify this list as necessary with the models they want to show. Subclasses are responsible for notifying data changes whenever - * this list is changed. + * Subclasses should modify this list as necessary with the models they want to show. Subclasses + * are responsible for notifying data changes whenever this list is changed. */ protected final List> models = new ArrayList<>(); private int spanCount = 1; private final HiddenEpoxyModel hiddenModel = new HiddenEpoxyModel(); /** - * Keeps track of view holders that are currently bound so we can save their state in {@link #onSaveInstanceState(Bundle)}. + * Keeps track of view holders that are currently bound so we can save their state in {@link + * #onSaveInstanceState(Bundle)}. */ private final BoundViewHolders boundViewHolders = new BoundViewHolders(); private ViewHolderState viewHolderState = new ViewHolderState(); @@ -63,8 +66,8 @@ public EpoxyAdapter() { } /** - * Enables support for automatically notifying model changes via {@link #notifyModelsChanged()}. If used, this should be called in the constructor, - * before any models are changed. + * Enables support for automatically notifying model changes via {@link #notifyModelsChanged()}. + * If used, this should be called in the constructor, before any models are changed. * * @see #notifyModelsChanged() */ @@ -85,11 +88,14 @@ protected void enableDiffing() { } /** - * Intelligently notify item changes by comparing the current {@link #models} list against the previous so you don't have to micromanage - * notification calls yourself. This may be prohibitively slow for large model lists (in the hundreds), in which case consider doing notification - * calls yourself. If you use this, all your view models must implement {@link EpoxyModel#hashCode()} to completely identify their state, so that - * changes to a model's content can be detected. Before using this you must enable it with {@link #enableDiffing()}, since keeping track of the - * model state adds extra computation time to all other data change notifications. + * Intelligently notify item changes by comparing the current {@link #models} list against the + * previous so you don't have to micromanage notification calls yourself. This may be + * prohibitively slow for large model lists (in the hundreds), in which case consider doing + * notification calls yourself. If you use this, all your view models must implement {@link + * EpoxyModel#hashCode()} to completely identify their state, so that changes to a model's content + * can be detected. Before using this you must enable it with {@link #enableDiffing()}, since + * keeping track of the model state adds extra computation time to all other data change + * notifications. * * @see #enableDiffing() */ @@ -143,7 +149,8 @@ public void onBindViewHolder(EpoxyViewHolder holder, int position, List } /** - * Called immediately after a model is bound to a view holder. Subclasses can override this if they want alerts on when a model is bound. + * Called immediately after a model is bound to a view holder. Subclasses can override this if + * they want alerts on when a model is bound. */ protected void onModelBound(EpoxyViewHolder holder, EpoxyModel model) { @@ -182,7 +189,8 @@ public void onViewRecycled(EpoxyViewHolder holder) { } /** - * Called immediately after a model is unbound from a view holder. Subclasses can override this if they want alerts on when a model is unbound. + * Called immediately after a model is unbound from a view holder. Subclasses can override this if + * they want alerts on when a model is unbound. */ protected void onModelUnbound(EpoxyViewHolder holder, EpoxyModel model) { @@ -208,8 +216,8 @@ public void onRestoreInstanceState(@Nullable Bundle inState) { // is more difficult to update view state once they are bound if (boundViewHolders.size() > 0) { throw new IllegalStateException( - "State cannot be restored once views have been bound. It should be done before adding " + - "the adapter to the recycler view."); + "State cannot be restored once views have been bound. It should be done before adding " + + "the adapter to the recycler view."); } if (inState != null) { @@ -218,7 +226,8 @@ public void onRestoreInstanceState(@Nullable Bundle inState) { } /** - * Notify that the given model has had its data changed. It should only be called if the model retained the same position. + * Notify that the given model has had its data changed. It should only be called if the model + * retained the same position. */ protected void notifyModelChanged(EpoxyModel model) { int index = models.indexOf(model); @@ -255,7 +264,8 @@ protected void insertModelAfter(EpoxyModel modelToInsert, EpoxyModel model } /** - * If the given model exists it is removed and an item removal is notified. Otherwise this does nothing. + * If the given model exists it is removed and an item removal is notified. Otherwise this does + * nothing. */ protected void removeModel(EpoxyModel model) { int index = models.indexOf(model); @@ -263,12 +273,12 @@ protected void removeModel(EpoxyModel model) { models.remove(index); notifyItemRemoved(index); } - } /** - * Removes all models after the given model, which must have already been added. An example use case is you want to keep a header but clear - * everything else, like in the case of refreshing data. + * Removes all models after the given model, which must have already been added. An example use + * case is you want to keep a header but clear everything else, like in the case of refreshing + * data. */ protected void removeAllAfterModel(EpoxyModel model) { List> modelsToRemove = getAllModelsAfter(model); @@ -314,8 +324,8 @@ protected void hideAllAfterModel(EpoxyModel model) { } /** - * Returns a list of all items in {@link #models} that occur after the given model. Any changes to the returned sublist will be reflected in the - * original {@link #models} list. + * Returns a list of all items in {@link #models} that occur after the given model. Any changes to + * the returned sublist will be reflected in the original {@link #models} list. * * @param model Must exists in {@link #models}. */ @@ -342,4 +352,4 @@ public int getSpanCount() { public boolean isMultiSpan() { return spanCount > 1; } -} \ No newline at end of file +} diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyItemAnimator.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyItemAnimator.java deleted file mode 100755 index a0907d91a0..0000000000 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyItemAnimator.java +++ /dev/null @@ -1,19 +0,0 @@ - -package com.airbnb.epoxy; - -import android.support.annotation.NonNull; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.RecyclerView.ViewHolder; - -import java.util.List; - -/** - * Item animator for use with {@link EpoxyAdapter} so that view holders are always reused during animations. - */ -public class EpoxyItemAnimator extends DefaultItemAnimator { - @Override - public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder, - @NonNull List payloads) { - return true; - } -} diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyViewHolder.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyViewHolder.java index 2de5a8db94..a2e7f79cf8 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyViewHolder.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyViewHolder.java @@ -57,10 +57,10 @@ private void assertBound() { @Override public String toString() { - return "EpoxyViewHolder{" + - "epoxyModel=" + epoxyModel + - ", view=" + itemView + - ", super=" + super.toString() + - '}'; + return "EpoxyViewHolder{" + + "epoxyModel=" + epoxyModel + + ", view=" + itemView + + ", super=" + super.toString() + + '}'; } } diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/HiddenEpoxyModel.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/HiddenEpoxyModel.java index a222db17bc..dcf5b1da37 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/HiddenEpoxyModel.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/HiddenEpoxyModel.java @@ -6,8 +6,9 @@ import com.airbnb.viewmodeladapter.R; /** - * Used by the {@link EpoxyAdapter} as a placeholder for when {@link EpoxyModel#isShown()} is false. Using a zero height and width {@link Space} - * view, as well as 0 span size, to exclude itself from view. + * Used by the {@link EpoxyAdapter} as a placeholder for when {@link EpoxyModel#isShown()} is false. + * Using a zero height and width {@link Space} view, as well as 0 span size, to exclude itself from + * view. */ class HiddenEpoxyModel extends EpoxyModel { @Override diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/ModelState.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/ModelState.java index bed188b7e2..6f30e694d6 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/ModelState.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/ModelState.java @@ -6,33 +6,37 @@ /** Helper to store relevant information about a model that we need to determine if it changed. */ class ModelState { - /* - * To have enough items in the pool it should be twice as big as the list size, since we track old and new list state. It's hard to predict - * list size and some users may have long lists that this won't be well suited to. It may be worth looking into dynamically resizing this - * based on list size. + /** + * To have enough items in the pool it should be twice as big as the list size, since we track old + * and new list state. It's hard to predict list size and some users may have long lists that this + * won't be well suited to. It may be worth looking into dynamically resizing this based on list + * size. */ - private static final Pools.Pool pool = new Pools.SimplePool<>(200); + private static final Pools.Pool POOL = new Pools.SimplePool<>(200); long id; int hashCode; int position; /** - * A link to the item with the same id in the other list when diffing two lists. This will be null if the item doesn't exist, in the case of - * insertions or removals. This is an optimization to prevent having to look up the matching pair in a hash map every time. + * A link to the item with the same id in the other list when diffing two lists. This will be null + * if the item doesn't exist, in the case of insertions or removals. This is an optimization to + * prevent having to look up the matching pair in a hash map every time. */ ModelState pair; /** - * How many movement operations have been applied to this item in order to update its position. As we find more item movements we need to update the - * position of affected items in the list in order to correctly calculate the next movement. Instead of iterating through all items in the list - * every time a movement operation happens we keep track of how many of these operations have been applied to an item, and apply all new operations - * in order when we need to get this item's up to date position. + * How many movement operations have been applied to this item in order to update its position. As + * we find more item movements we need to update the position of affected items in the list in + * order to correctly calculate the next movement. Instead of iterating through all items in the + * list every time a movement operation happens we keep track of how many of these operations have + * been applied to an item, and apply all new operations in order when we need to get this item's + * up to date position. */ int lastMoveOp; static ModelState build(EpoxyModel model, int position) { - ModelState state = pool.acquire(); + ModelState state = POOL.acquire(); if (state == null) { state = new ModelState(); } @@ -53,17 +57,17 @@ static void release(Collection states) { } public static void release(ModelState state) { - pool.release(state); + POOL.release(state); } @Override public String toString() { - return "ModelState{" + - "id=" + id + - ", hashCode=" + hashCode + - ", position=" + position + - ", pair=" + pair + - ", lastMoveOp=" + lastMoveOp + - '}'; + return "ModelState{" + + "id=" + id + + ", hashCode=" + hashCode + + ", position=" + position + + ", pair=" + pair + + ", lastMoveOp=" + lastMoveOp + + '}'; } } diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/SimpleEpoxyModel.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/SimpleEpoxyModel.java index baf8aa42ee..bd8a6a0768 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/SimpleEpoxyModel.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/SimpleEpoxyModel.java @@ -71,8 +71,8 @@ public boolean equals(Object o) { if (spanCount != that.spanCount) { return false; } - return onClickListener != null ? onClickListener.equals(that.onClickListener) : - that.onClickListener == null; + return onClickListener != null ? onClickListener.equals(that.onClickListener) + : that.onClickListener == null; } @Override @@ -83,4 +83,4 @@ public int hashCode() { result = 31 * result + spanCount; return result; } -} \ No newline at end of file +} diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/UpdateOp.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/UpdateOp.java index 2f48f16d60..267d6da6e9 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/UpdateOp.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/UpdateOp.java @@ -12,15 +12,15 @@ class UpdateOp { private static final Pools.Pool UPDATE_OP_POOL = new Pools.SimplePool<>(10); - @IntDef({Add, Remove, Update, Move}) + @IntDef({ADD, REMOVE, UPDATE, MOVE}) @Retention(RetentionPolicy.SOURCE) @interface Type { } - static final int Add = 0; - static final int Remove = 1; - static final int Update = 2; - static final int Move = 3; + static final int ADD = 0; + static final int REMOVE = 1; + static final int UPDATE = 2; + static final int MOVE = 3; @Type int type; int positionStart; @@ -55,10 +55,10 @@ static void release(List diff) { @Override public String toString() { - return "UpdateOp{" + - "type=" + type + - ", positionStart=" + positionStart + - ", itemCount=" + itemCount + - '}'; + return "UpdateOp{" + + "type=" + type + + ", positionStart=" + positionStart + + ", itemCount=" + itemCount + + '}'; } -} \ No newline at end of file +} diff --git a/epoxy-adapter/src/main/java/com/airbnb/epoxy/ViewHolderState.java b/epoxy-adapter/src/main/java/com/airbnb/epoxy/ViewHolderState.java index 801b1d9278..7416d4014a 100755 --- a/epoxy-adapter/src/main/java/com/airbnb/epoxy/ViewHolderState.java +++ b/epoxy-adapter/src/main/java/com/airbnb/epoxy/ViewHolderState.java @@ -15,15 +15,20 @@ import java.util.Collection; /** - * Helper for {@link EpoxyAdapter} to store the state of Views in the adapter. This is useful for saving changes due to user input, such as text - * input or selection, when a view is scrolled off screen or if the adapter needs to be recreated. + * Helper for {@link EpoxyAdapter} to store the state of Views in the adapter. This is useful for + * saving changes due to user input, such as text input or selection, when a view is scrolled off + * screen or if the adapter needs to be recreated. *

- * This saved state is separate from the state represented by a {@link EpoxyModel}, which should represent the more permanent state of the data shown - * in the view. This class stores transient state that is added to the View after it is bound to a {@link EpoxyModel}. For example, a {@link EpoxyModel} - * may inflate and bind an EditText and then be responsible for styling it and attaching listeners. If the user then inputs text, scrolls the view - * offscreen and then scrolls back, this class will preserve the inputted text without the {@link EpoxyModel} needing to be aware of its existence. + * This saved state is separate from the state represented by a {@link EpoxyModel}, which should + * represent the more permanent state of the data shown in the view. This class stores transient + * state that is added to the View after it is bound to a {@link EpoxyModel}. For example, a {@link + * EpoxyModel} may inflate and bind an EditText and then be responsible for styling it and attaching + * listeners. If the user then inputs text, scrolls the view offscreen and then scrolls back, this + * class will preserve the inputted text without the {@link EpoxyModel} needing to be aware of its + * existence. *

- * This class relies on the adapter having stable ids, as the state of a view is mapped to the id of the {@link EpoxyModel}. + * This class relies on the adapter having stable ids, as the state of a view is mapped to the id of + * the {@link EpoxyModel}. */ @SuppressWarnings("WeakerAccess") class ViewHolderState extends LongSparseArray implements Parcelable { @@ -98,7 +103,8 @@ public void save(EpoxyViewHolder holder) { } /** - * If a state was previously saved for this view holder via {@link #save} it will be restored here. + * If a state was previously saved for this view holder via {@link #save} it will be restored + * here. */ public void restore(EpoxyViewHolder holder) { if (!holder.getModel().shouldSaveViewState()) { @@ -112,7 +118,8 @@ public void restore(EpoxyViewHolder holder) { } /** - * A wrapper around a sparse array as a helper to save the state of a view. This also adds parcelable support. + * A wrapper around a sparse array as a helper to save the state of a view. This also adds + * parcelable support. */ public static class ViewState extends SparseArray implements Parcelable { @@ -143,8 +150,9 @@ public void restore(View view) { } /** - * If a view hasn't had an id set we need to set a temporary one in order to save state, since a view won't save its state unless it has an id. - * The view's id is also the key into the sparse array for its saved state, so the temporary one we choose just needs to be consistent between + * If a view hasn't had an id set we need to set a temporary one in order to save state, since a + * view won't save its state unless it has an id. The view's id is also the key into the sparse + * array for its saved state, so the temporary one we choose just needs to be consistent between * saving and restoring state. */ private void setIdIfNoneExists(View view) { diff --git a/epoxy-model/build.gradle b/epoxy-model/build.gradle index 682c9cc4ab..4b565e64be 100755 --- a/epoxy-model/build.gradle +++ b/epoxy-model/build.gradle @@ -7,4 +7,9 @@ dependencies { compile 'com.android.support:support-annotations:24.1.1' } +checkstyle { + configFile rootProject.file('checkstyle.xml') + showViolations true +} + apply from: rootProject.file('gradle/gradle-maven-push.gradle') \ No newline at end of file diff --git a/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyAttribute.java b/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyAttribute.java index b5d8858c34..508cba1988 100755 --- a/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyAttribute.java +++ b/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyAttribute.java @@ -13,4 +13,4 @@ @Target(ElementType.FIELD) @Retention(RetentionPolicy.CLASS) public @interface EpoxyAttribute { -} \ No newline at end of file +} diff --git a/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyModel.java b/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyModel.java index df516c3c26..9d6b1dafcd 100755 --- a/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyModel.java +++ b/epoxy-model/src/main/java/com/airbnb/epoxy/EpoxyModel.java @@ -159,10 +159,10 @@ public boolean shouldSaveViewState() { @Override public String toString() { - return "EpoxyModel{" + - "id=" + id + - ", layout=" + layout + - ", shown=" + shown + - '}'; + return "EpoxyModel{" + + "id=" + id + + ", layout=" + layout + + ", shown=" + shown + + '}'; } -} \ No newline at end of file +} diff --git a/epoxy-processor/build.gradle b/epoxy-processor/build.gradle index ab52b84110..e9e260cd3b 100755 --- a/epoxy-processor/build.gradle +++ b/epoxy-processor/build.gradle @@ -14,4 +14,9 @@ dependencies { compile 'com.android.support:support-annotations:24.1.1' } +checkstyle { + configFile rootProject.file('checkstyle.xml') + showViolations true +} + apply from: rootProject.file('gradle/gradle-maven-push.gradle') diff --git a/epoxy-processor/src/main/java/com/airbnb/epoxy/AttributeInfo.java b/epoxy-processor/src/main/java/com/airbnb/epoxy/AttributeInfo.java index 7d43ef0b83..047a05d61c 100755 --- a/epoxy-processor/src/main/java/com/airbnb/epoxy/AttributeInfo.java +++ b/epoxy-processor/src/main/java/com/airbnb/epoxy/AttributeInfo.java @@ -19,10 +19,14 @@ public class AttributeInfo { private final List getterAnnotations = new ArrayList<>(); private final String name; private final TypeName type; - /** Track whether there is a setter method for this attribute on a super class so that we can call through to super. */ + /** + * Track whether there is a setter method for this attribute on a super class so that we can call + * through to super. + */ private final boolean hasSuperSetter; - public AttributeInfo(String name, TypeName type, List annotationMirrors, boolean hasSuperSetter) { + public AttributeInfo(String name, TypeName type, + List annotationMirrors, boolean hasSuperSetter) { this.name = name; this.type = type; this.hasSuperSetter = hasSuperSetter; @@ -30,8 +34,9 @@ public AttributeInfo(String name, TypeName type, List annotationMirrors) { for (AnnotationMirror annotationMirror : annotationMirrors) { @@ -40,7 +45,8 @@ private void buildAnnotationLists(List annotationMir continue; } - ClassName annotationClass = ClassName.bestGuess(annotationMirror.getAnnotationType().toString()); + ClassName annotationClass = + ClassName.bestGuess(annotationMirror.getAnnotationType().toString()); if (annotationClass.equals(ClassName.get(EpoxyAttribute.class))) { // Don't include our own annotation continue; @@ -83,10 +89,10 @@ public boolean hasSuperSetterMethod() { @Override public String toString() { - return "ModelAttributeData{" + - "name='" + name + '\'' + - ", type=" + type + - '}'; + return "ModelAttributeData{" + + "name='" + name + '\'' + + ", type=" + type + + '}'; } @Override diff --git a/epoxy-processor/src/main/java/com/airbnb/epoxy/ClassToGenerateInfo.java b/epoxy-processor/src/main/java/com/airbnb/epoxy/ClassToGenerateInfo.java index d61fa1e56d..7035172fb9 100755 --- a/epoxy-processor/src/main/java/com/airbnb/epoxy/ClassToGenerateInfo.java +++ b/epoxy-processor/src/main/java/com/airbnb/epoxy/ClassToGenerateInfo.java @@ -34,7 +34,8 @@ public class ClassToGenerateInfo { private final List typeVariableNames = new ArrayList<>(); private final List constructors = new ArrayList<>(); - public ClassToGenerateInfo(TypeElement originalClassName, ClassName generatedClassName, boolean isOriginalClassAbstract) { + public ClassToGenerateInfo(TypeElement originalClassName, ClassName generatedClassName, + boolean isOriginalClassAbstract) { this.originalClassName = ParameterizedTypeName.get(originalClassName.asType()); this.originalClassNameWithoutType = ClassName.get(originalClassName); @@ -45,14 +46,17 @@ public ClassToGenerateInfo(TypeElement originalClassName, ClassName generatedCla // Get information about constructors on the original class so we can duplicate // them in the generated class and call through to super with the proper parameters for (Element subElement : originalClassName.getEnclosedElements()) { - if (subElement.getKind() == ElementKind.CONSTRUCTOR && !subElement.getModifiers().contains(Modifier.PRIVATE)) { - List params = subElement.asType().accept(constructorVisitor, null); - constructors.add(new ConstructorInfo(subElement.getModifiers(), buildConstructorParamList(params))); + if (subElement.getKind() == ElementKind.CONSTRUCTOR + && !subElement.getModifiers().contains(Modifier.PRIVATE)) { + List params = subElement.asType().accept(CONSTRUCTOR_VISITOR, null); + constructors + .add(new ConstructorInfo(subElement.getModifiers(), buildConstructorParamList(params))); } } if (!typeVariableNames.isEmpty()) { - TypeVariableName[] typeArguments = typeVariableNames.toArray(new TypeVariableName[typeVariableNames.size()]); + TypeVariableName[] typeArguments = + typeVariableNames.toArray(new TypeVariableName[typeVariableNames.size()]); this.parameterizedClassName = ParameterizedTypeName.get(generatedClassName, typeArguments); } else { this.parameterizedClassName = generatedClassName; @@ -74,11 +78,12 @@ private List buildConstructorParamList(List return result; } - private static final TypeVisitor, Void> constructorVisitor = new SimpleTypeVisitor6, Void>() { - public List visitExecutable(ExecutableType t, Void v) { - return t.getParameterTypes(); - } - }; + private static final TypeVisitor, Void> CONSTRUCTOR_VISITOR = + new SimpleTypeVisitor6, Void>() { + public List visitExecutable(ExecutableType t, Void v) { + return t.getParameterTypes(); + } + }; public void addAttribute(AttributeInfo attributeInfo) { this.attributeInfo.add(attributeInfo); diff --git a/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessor.java b/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessor.java index 1b8f7dc40e..cfd10cf26c 100755 --- a/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessor.java +++ b/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessor.java @@ -62,7 +62,7 @@ @AutoService(Processor.class) public class EpoxyProcessor extends AbstractProcessor { private static final String GENERATED_CLASS_NAME_SUFFIX = "_"; - private static TypeMirror EPOXY_MODEL_TYPE; + private static TypeMirror epoxyModelType; private Filer filer; private Messager messager; @@ -75,7 +75,7 @@ public synchronized void init(ProcessingEnvironment processingEnv) { filer = processingEnv.getFiler(); messager = processingEnv.getMessager(); elementUtils = processingEnv.getElementUtils(); - EPOXY_MODEL_TYPE = elementUtils.getTypeElement(EpoxyModel.class.getCanonicalName()).asType(); + epoxyModelType = elementUtils.getTypeElement(EpoxyModel.class.getCanonicalName()).asType(); typeUtils = processingEnv.getTypeUtils(); } @@ -115,7 +115,9 @@ public boolean process(Set annotations, RoundEnvironment } private void processAttribute(Element attribute, - Map modelClassMap) throws EpoxyProcessorException { + Map modelClassMap) + throws EpoxyProcessorException { + validateAccessibleViaGeneratedCode(attribute); TypeElement classElement = (TypeElement) attribute.getEnclosingElement(); @@ -133,7 +135,7 @@ private void processAttribute(Element attribute, * Private methods are ignored since the generated subclass can't call super on those. */ private boolean hasSuperMethod(TypeElement classElement, String methodName) { - if (!isSubtype(classElement.asType(), EPOXY_MODEL_TYPE)) { + if (!isSubtype(classElement.asType(), epoxyModelType)) { return false; } @@ -146,12 +148,13 @@ private boolean hasSuperMethod(TypeElement classElement, String methodName) { } Element superClass = typeUtils.asElement(classElement.getSuperclass()); - return (superClass instanceof TypeElement) && - hasSuperMethod((TypeElement) superClass, methodName); + return (superClass instanceof TypeElement) + && hasSuperMethod((TypeElement) superClass, methodName); } private void validateAccessibleViaGeneratedCode(Element attribute) throws EpoxyProcessorException { + TypeElement enclosingElement = (TypeElement) attribute.getEnclosingElement(); // Verify method modifiers. @@ -191,6 +194,7 @@ private void validateAccessibleViaGeneratedCode(Element attribute) throws private ClassToGenerateInfo getOrCreateTargetClass( Map modelClassMap, TypeElement classElement) throws EpoxyProcessorException { + ClassToGenerateInfo classToGenerateInfo = modelClassMap.get(classElement); boolean isFinal = classElement.getModifiers().contains(Modifier.FINAL); @@ -199,9 +203,9 @@ private ClassToGenerateInfo getOrCreateTargetClass( EpoxyAttribute.class.getSimpleName(), classElement.getSimpleName()); } - if (!isSubtype(classElement.asType(), EPOXY_MODEL_TYPE)) { + if (!isSubtype(classElement.asType(), epoxyModelType)) { throwError("Class with %s annotations must extend %s (%s)", - EpoxyAttribute.class.getSimpleName(), EPOXY_MODEL_TYPE, + EpoxyAttribute.class.getSimpleName(), epoxyModelType, classElement.getSimpleName()); } @@ -252,7 +256,8 @@ private boolean isSubtype(TypeMirror e1, TypeMirror e2) { private void generateClassForModel(ClassToGenerateInfo info) throws IOException { if (info.isOriginalClassAbstract()) { - // Don't extend classes that are abstract. If they don't contain all required methods then our generated class won't compile + // Don't extend classes that are abstract. If they don't contain all required + // methods then our generated class won't compile return; } @@ -492,7 +497,8 @@ private void writeError(Exception e) { messager.printMessage(Diagnostic.Kind.ERROR, e.toString()); } - private void throwError(String msg, Object... args) throws EpoxyProcessorException { + private void throwError(String msg, Object... args) + throws EpoxyProcessorException { throw new EpoxyProcessorException(String.format(msg, args)); } } diff --git a/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessorException.java b/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessorException.java index 44fa851ff2..c043e0bd13 100755 --- a/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessorException.java +++ b/epoxy-processor/src/main/java/com/airbnb/epoxy/EpoxyProcessorException.java @@ -1,7 +1,7 @@ package com.airbnb.epoxy; -class EpoxyProcessorException extends RuntimeException { +class EpoxyProcessorException extends Exception { EpoxyProcessorException(String message) { super(message); } diff --git a/epoxy-processor/src/test/java/com/airbnb/epoxy/EpoxyProcessorTest.java b/epoxy-processor/src/test/java/com/airbnb/epoxy/EpoxyProcessorTest.java index bef9a021a9..5bc09b43de 100755 --- a/epoxy-processor/src/test/java/com/airbnb/epoxy/EpoxyProcessorTest.java +++ b/epoxy-processor/src/test/java/com/airbnb/epoxy/EpoxyProcessorTest.java @@ -200,4 +200,4 @@ public void testModelAsInnerClassFails() { .failsToCompile() .withErrorContaining("Nested classes"); } -} \ No newline at end of file +} diff --git a/epoxy-sample/src/main/java/com/airbnb/epoxy/MainActivity.java b/epoxy-sample/src/main/java/com/airbnb/epoxy/MainActivity.java index 75192e9d2a..cf76d885d3 100755 --- a/epoxy-sample/src/main/java/com/airbnb/epoxy/MainActivity.java +++ b/epoxy-sample/src/main/java/com/airbnb/epoxy/MainActivity.java @@ -32,4 +32,4 @@ static class Adapter extends EpoxyAdapter { .caption("caption")); } } -} \ No newline at end of file +} diff --git a/epoxy-sample/src/main/java/com/airbnb/epoxy/ModelWithSuperAttributes.java b/epoxy-sample/src/main/java/com/airbnb/epoxy/ModelWithSuperAttributes.java deleted file mode 100755 index 60c84782a4..0000000000 --- a/epoxy-sample/src/main/java/com/airbnb/epoxy/ModelWithSuperAttributes.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.airbnb.epoxy; - -public class ModelWithSuperAttributes extends EpoxyModel { - - @EpoxyAttribute int superValue; - - @Override - protected int getDefaultLayout() { - return 0; - } - - public static class SubModelWithSuperAttributes extends ModelWithSuperAttributes { - @EpoxyAttribute int subValue; - } -} \ No newline at end of file diff --git a/epoxy-sample/src/main/java/com/airbnb/epoxy/NumberModel.java b/epoxy-sample/src/main/java/com/airbnb/epoxy/NumberModel.java deleted file mode 100755 index 25e8fd35e9..0000000000 --- a/epoxy-sample/src/main/java/com/airbnb/epoxy/NumberModel.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.airbnb.epoxy; - -import android.widget.TextView; - -import com.airbnb.epoxy.EpoxyModel; -import com.airbnb.epoxy.EpoxyAttribute; - -import java.util.Random; - -public class NumberModel extends EpoxyModel { - private static final Random RANDOM = new Random(10); - @EpoxyAttribute int value; - - public NumberModel() { - randomizeValue(); - id(value); - } - - public void randomizeValue() { - value = RANDOM.nextInt(); - } - - @Override - public void bind(TextView view) { - super.bind(view); - view.setText("" + value); - } - - @Override - public int getDefaultLayout() { - return R.layout.number_view; - } -} \ No newline at end of file