From 84a9818594c57d1108c990f8f3a4c1b2aec02262 Mon Sep 17 00:00:00 2001 From: Jorge Garrido Date: Mon, 1 May 2017 13:53:29 +0200 Subject: [PATCH] Create DiffRVRendererAdapter to use RecyclerView's DiffUtil (#36) * Update support library in order to add the DiffUtil, also update gradle version * Add DiffRVRendererAdapter class to take advantage of the DiffUtil in our RendererAdapters * Implement the Diff * Create a renderer with the hability of remove items from the list in order to show the Diff animation * Fix checkstyle and change android sdk version on travis * Fix lint * Remove DiffRVRendererAdapter and move update to RVRendererAdapter then fix the sample project * Rename the class RemoveItemCallback to RemovableVideoRenderer.Listener * Rename the method removeItem in RemoveItemCallback to onRemoveButtonTapped * Add a documentation comment for our new diffUpdate method * Override hashCode in order to fix the checkstyle --- .travis.yml | 7 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- renderers/build.gradle | 11 +-- .../renderers/RVRendererAdapter.java | 68 +++++++++++++++++++ sample/build.gradle | 11 +-- .../renderers/sample/model/Video.java | 17 +++++ .../sample/ui/RecyclerViewActivity.java | 16 ++++- .../ui/renderers/RemovableVideoRenderer.java | 38 +++++++++++ sample/src/main/res/values/strings.xml | 1 + 10 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 sample/src/main/java/com/pedrogomez/renderers/sample/ui/renderers/RemovableVideoRenderer.java diff --git a/.travis.yml b/.travis.yml index 91bb968..b95ce80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,11 @@ language: android android: components: - tools - - build-tools-23.0.2 - - android-23 + - build-tools-25.0.2 + - android-25 - extra-android-support - extra-google-m2repository - extra-android-m2repository -script: +script: - ./gradlew checkstyle build - diff --git a/build.gradle b/build.gradle index 316fafc..97e1b72 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.0' + classpath 'com.android.tools.build:gradle:2.3.1' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 01babc0..d40838f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Jan 03 17:21:12 CET 2016 +#Fri Apr 07 09:29:52 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/renderers/build.gradle b/renderers/build.gradle index d60a429..f3531ca 100644 --- a/renderers/build.gradle +++ b/renderers/build.gradle @@ -2,12 +2,12 @@ apply plugin: 'com.android.library' apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion '25.0.2' defaultConfig { minSdkVersion 10 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.0" } @@ -16,11 +16,14 @@ android { minifyEnabled false } } + lintOptions { + abortOnError false + } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:recyclerview-v7:23.1.1' + compile 'com.android.support:recyclerview-v7:25.3.1' testCompile 'junit:junit:4.12' testCompile "org.mockito:mockito-core:1.9.5" testCompile 'org.robolectric:robolectric:2.4' diff --git a/renderers/src/main/java/com/pedrogomez/renderers/RVRendererAdapter.java b/renderers/src/main/java/com/pedrogomez/renderers/RVRendererAdapter.java index 144dc76..cdbe68b 100644 --- a/renderers/src/main/java/com/pedrogomez/renderers/RVRendererAdapter.java +++ b/renderers/src/main/java/com/pedrogomez/renderers/RVRendererAdapter.java @@ -15,11 +15,13 @@ */ package com.pedrogomez.renderers; +import android.support.v7.util.DiffUtil; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.ViewGroup; import com.pedrogomez.renderers.exception.NullRendererBuiltException; import java.util.Collection; +import java.util.List; /** * RecyclerView.Adapter extension created to work RendererBuilders and Renderer instances. Other @@ -187,4 +189,70 @@ protected AdapteeCollection getCollection() { protected void updateRendererExtraValues(T content, Renderer renderer, int position) { } + + /** + * Provides a ready to use diff update for our adapter based on the implementation of the + * standard equals method from Object + * + * @param newList to refresh our content + */ + public void diffUpdate(List newList) { + if (getCollection().size() == 0) { + this.addAll(newList); + notifyDataSetChanged(); + } else { + DiffCallbacks diffCallbacks = new DiffCallbacks(newList); + DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallbacks); + + this.clear(); + this.addAll(newList); + diffResult.dispatchUpdatesTo(this); + } + } + + private class DiffCallbacks extends DiffUtil.Callback { + + private final List newList; + + private int oldItemPosition; + + private boolean deep; + + DiffCallbacks(List newList) { + this.newList = newList; + } + + @Override public int getOldListSize() { + return collection.size(); + } + + @Override public int getNewListSize() { + return newList.size(); + } + + @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + this.deep = false; + this.oldItemPosition = oldItemPosition; + return equals(newList.get(newItemPosition)); + } + + @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + this.deep = true; + this.oldItemPosition = oldItemPosition; + return equals(newList.get(newItemPosition)); + } + + @Override public boolean equals(Object newItem) { + Object current = collection.get(oldItemPosition); + if (deep) { + return newItem.equals(current); + } else { + return newItem.getClass().equals(current.getClass()); + } + } + + @Override public int hashCode() { + return super.hashCode(); + } + } } diff --git a/sample/build.gradle b/sample/build.gradle index 11e08f1..96bfdec 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion '25.0.2' defaultConfig { applicationId "com.github.pedrovgs.renderers.sample" minSdkVersion 14 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.0" } @@ -16,11 +16,14 @@ android { minifyEnabled false } } + lintOptions { + abortOnError false + } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:23.1.1' + compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.jakewharton:butterknife:7.0.1' compile 'com.squareup.picasso:picasso:2.5.2' compile project(':renderers') diff --git a/sample/src/main/java/com/pedrogomez/renderers/sample/model/Video.java b/sample/src/main/java/com/pedrogomez/renderers/sample/model/Video.java index 8a86f70..86ec1fa 100644 --- a/sample/src/main/java/com/pedrogomez/renderers/sample/model/Video.java +++ b/sample/src/main/java/com/pedrogomez/renderers/sample/model/Video.java @@ -67,4 +67,21 @@ public boolean isLive() { public void setLive(boolean live) { this.live = live; } + + @Override public boolean equals(Object obj) { + if (obj instanceof Video) { + Video other = (Video) obj; + return title.equals(other.title) + && thumbnail.equals(other.thumbnail) + && favorite == other.favorite + && liked == other.liked + && live == other.live; + } else { + return false; + } + } + + @Override public int hashCode() { + return super.hashCode(); + } } diff --git a/sample/src/main/java/com/pedrogomez/renderers/sample/ui/RecyclerViewActivity.java b/sample/src/main/java/com/pedrogomez/renderers/sample/ui/RecyclerViewActivity.java index ef32216..b1a17d0 100644 --- a/sample/src/main/java/com/pedrogomez/renderers/sample/ui/RecyclerViewActivity.java +++ b/sample/src/main/java/com/pedrogomez/renderers/sample/ui/RecyclerViewActivity.java @@ -29,6 +29,10 @@ import com.pedrogomez.renderers.sample.ui.renderers.FavoriteVideoRenderer; import com.pedrogomez.renderers.sample.ui.renderers.LikeVideoRenderer; import com.pedrogomez.renderers.sample.ui.renderers.LiveVideoRenderer; +import com.pedrogomez.renderers.sample.ui.renderers.RemovableVideoRenderer; + +import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -58,11 +62,17 @@ public class RecyclerViewActivity extends BaseActivity { private void initAdapter() { RandomVideoCollectionGenerator randomVideoCollectionGenerator = new RandomVideoCollectionGenerator(); - AdapteeCollection