├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ ├── styles.xml
│ │ │ └── colors_material.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ └── list_item_wizard.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ └── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ └── me
│ │ │ └── saket
│ │ │ └── rxdiffutils
│ │ │ ├── App.java
│ │ │ ├── Intents.java
│ │ │ ├── Wizard.java
│ │ │ ├── WizardDiffCallbacks.java
│ │ │ ├── RxDiffUtil.java
│ │ │ ├── SimpleDiffUtilCallbacks.java
│ │ │ ├── MinistryOfMagic.java
│ │ │ ├── MainActivity.java
│ │ │ └── WizardsAdapter.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saket/RxDiffUtil/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Rx.DiffUtils
3 | Search wizards…
4 |
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jan 19 14:47:35 IST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | @color/white
4 | @color/gray_100
5 | @color/teal_A700
6 | @color/white
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/App.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import android.app.Application;
4 | import timber.log.Timber;
5 | import timber.log.Timber.DebugTree;
6 |
7 | public class App extends Application {
8 |
9 | @Override
10 | public void onCreate() {
11 | super.onCreate();
12 | Timber.plant(new DebugTree());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/Intents.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import android.content.Intent;
4 | import android.net.Uri;
5 |
6 | public class Intents {
7 |
8 | public static Intent forGoogleSearch(String query) {
9 | return new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://www.google.com/search?q=" + query));
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/Wizard.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import com.google.auto.value.AutoValue;
4 |
5 | @AutoValue
6 | public abstract class Wizard {
7 |
8 | public abstract long id();
9 |
10 | public abstract String name();
11 |
12 | public abstract String house();
13 |
14 | public static Wizard create(long id, String name, String house) {
15 | return new AutoValue_Wizard(id, name, house);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 | build/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio stuff
31 | .idea/
32 | .navigation/
33 | captures/
34 | *.iml
35 |
36 | ### Android Patch ###
37 | gen-external-apklibs
38 |
39 | # OS specific ignores
40 | .DS_Store
41 | *~
42 | *.swp
43 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/WizardDiffCallbacks.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import java.util.List;
4 |
5 | public class WizardDiffCallbacks extends SimpleDiffUtilCallbacks {
6 |
7 | public static WizardDiffCallbacks create(List oldItems, List newItems) {
8 | return new WizardDiffCallbacks(oldItems, newItems);
9 | }
10 |
11 | private WizardDiffCallbacks(List oldItems, List newItems) {
12 | super(oldItems, newItems);
13 | }
14 |
15 | @Override
16 | public boolean areItemsTheSame(Wizard oldItem, Wizard newItem) {
17 | return oldItem.id() == newItem.id();
18 | }
19 |
20 | @Override
21 | protected boolean areContentsTheSame(Wizard oldItem, Wizard newItem) {
22 | return oldItem.equals(newItem);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/RxDiffUtil.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import android.support.v7.util.DiffUtil;
4 | import android.support.v7.util.DiffUtil.DiffResult;
5 | import android.util.Pair;
6 |
7 | import java.util.Collections;
8 | import java.util.List;
9 |
10 | import io.reactivex.ObservableTransformer;
11 | import io.reactivex.functions.BiFunction;
12 |
13 | public class RxDiffUtil {
14 |
15 | public static ObservableTransformer, Pair, DiffResult>> calculateDiff(
16 | BiFunction, List, DiffUtil.Callback> diffCallbacks)
17 | {
18 | Pair, DiffUtil.DiffResult> initialPair = Pair.create(Collections.emptyList(), null);
19 | return upstream -> upstream
20 | .scan(initialPair, (latestPair, nextItems) -> {
21 | DiffUtil.Callback callback = diffCallbacks.apply(latestPair.first, nextItems);
22 | DiffUtil.DiffResult result = DiffUtil.calculateDiff(callback, true);
23 | return Pair.create(nextItems, result);
24 | })
25 | .skip(1); // downstream shouldn't receive seedPair.
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_wizard.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
25 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/SimpleDiffUtilCallbacks.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import android.support.v7.util.DiffUtil;
4 | import java.util.List;
5 |
6 | /**
7 | * DIffUtils.Callback + generics.
8 | */
9 | public abstract class SimpleDiffUtilCallbacks extends DiffUtil.Callback {
10 |
11 | private final List oldItems;
12 | private final List newItems;
13 |
14 | public SimpleDiffUtilCallbacks(List oldItems, List newItems) {
15 | this.oldItems = oldItems;
16 | this.newItems = newItems;
17 | }
18 |
19 | public abstract boolean areItemsTheSame(T oldItem, T newItem);
20 |
21 | protected abstract boolean areContentsTheSame(T oldItem, T newItem);
22 |
23 | @Override
24 | public final int getOldListSize() {
25 | return oldItems.size();
26 | }
27 |
28 | @Override
29 | public final int getNewListSize() {
30 | return newItems.size();
31 | }
32 |
33 | @Override
34 | public final boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
35 | T oldItem = oldItems.get(oldItemPosition);
36 | T newItem = newItems.get(newItemPosition);
37 | return areItemsTheSame(oldItem, newItem);
38 | }
39 |
40 | @Override
41 | public final boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
42 | T oldItem = oldItems.get(oldItemPosition);
43 | T newItem = newItems.get(newItemPosition);
44 | return areContentsTheSame(oldItem, newItem);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | ext.versions = [
4 | minSdk : 24,
5 | compileSdk : 26,
6 | androidTools : '26.0.2',
7 | supportLib : '27.0.2',
8 | autoValue : '1.4',
9 | autoValueMoshi: '0.4.3',
10 | retrofit : '2.2.0',
11 | rxBindings : '2.0.0',
12 | dagger : '2.10',
13 | butterKnife : '8.8.1',
14 | timber : '4.6.0',
15 | ]
16 |
17 | android {
18 | compileSdkVersion versions.compileSdk
19 |
20 | defaultConfig {
21 | applicationId "me.saket.rxdiffutils"
22 | minSdkVersion versions.minSdk
23 | targetSdkVersion versions.compileSdk
24 | versionCode 1
25 | versionName "1.0"
26 | }
27 |
28 | buildTypes {
29 | release {
30 | minifyEnabled false
31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
32 | }
33 | }
34 |
35 | compileOptions {
36 | targetCompatibility 1.8
37 | sourceCompatibility 1.8
38 | }
39 | }
40 |
41 | dependencies {
42 | implementation "com.android.support:appcompat-v7:$versions.supportLib"
43 | implementation "com.android.support:recyclerview-v7:$versions.supportLib"
44 | annotationProcessor "com.google.auto.value:auto-value:$versions.autoValue"
45 | provided "com.jakewharton.auto.value:auto-value-annotations:$versions.autoValue"
46 | implementation "com.jakewharton.timber:timber:$versions.timber"
47 | implementation "com.jakewharton:butterknife:$versions.butterKnife"
48 | annotationProcessor "com.jakewharton:butterknife-compiler:$versions.butterKnife"
49 | implementation 'io.reactivex.rxjava2:rxjava:2.1.7'
50 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
51 | implementation "com.jakewharton.rxbinding2:rxbinding:$versions.rxBindings"
52 | implementation "com.jakewharton.rxrelay2:rxrelay:2.0.0"
53 | implementation "com.mikepenz:itemanimators:1.0.1@aar"
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/MinistryOfMagic.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import io.reactivex.Single;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Locale;
7 | import java.util.stream.Collectors;
8 |
9 | public class MinistryOfMagic {
10 |
11 | private static final List STUDENTS = new ArrayList() {{
12 | add(Wizard.create(1, "Hannah Abbott", "Hufflepuff"));
13 | add(Wizard.create(2, "Sirius Black", "Gryffindor"));
14 | add(Wizard.create(3, "Lavender Brown", "Gryffindor"));
15 | add(Wizard.create(4, "Millicent Bulstrode", "Slytherin"));
16 | add(Wizard.create(5, "Dennis Creevey", "Gryffindor"));
17 | add(Wizard.create(6, "Roger Davies", "Ravenclaw"));
18 | add(Wizard.create(7, "Cedric Diggory", "Hufflepuff"));
19 | add(Wizard.create(8, "Justin Finch-Fletchley", "Hufflepuff"));
20 | add(Wizard.create(9, "Ernie Macmillan", "Hufflepuff"));
21 | add(Wizard.create(10, "Zacharias Smith", "Hufflepuff"));
22 | add(Wizard.create(11, "Vincent Crabbe", "Slytherin"));
23 | add(Wizard.create(12, "Marcus Flint", "Slytherin"));
24 | add(Wizard.create(13, "Gregory Goyle", "Slytherin"));
25 | add(Wizard.create(14, "Draco Malfoy", "Slytherin"));
26 | add(Wizard.create(15, "Graham Montague", "Slytherin"));
27 | add(Wizard.create(16, "Pansy Parkinson", "Slytherin"));
28 | add(Wizard.create(17, "Alicia Spinnet", "Gryffindor"));
29 | add(Wizard.create(18, "Dean Thomas", "Gryffindor"));
30 | add(Wizard.create(19, "Ron Weasley", "Gryffindor"));
31 | add(Wizard.create(20, "Ginny Weasley", "Gryffindor"));
32 | add(Wizard.create(21, "Katie Bell", "Gryffindor"));
33 | add(Wizard.create(22, "Colin Creevey", "Gryffindor"));
34 | add(Wizard.create(23, "Seamus Finnigan", "Gryffindor"));
35 | add(Wizard.create(24, "Hermione Granger", "Gryffindor"));
36 | add(Wizard.create(25, "Harry Potter", "Gryffindor"));
37 | }};
38 |
39 | Single> search(String query) {
40 | if (query.isEmpty()) {
41 | return Single.just(STUDENTS);
42 | }
43 |
44 | return Single.fromCallable(() -> STUDENTS.stream()
45 | .filter(wizard -> wizard.name().toLowerCase(Locale.ENGLISH).startsWith(query.toLowerCase(Locale.ENGLISH)))
46 | .collect(Collectors.toList()));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/me/saket/rxdiffutils/MainActivity.java:
--------------------------------------------------------------------------------
1 | package me.saket.rxdiffutils;
2 |
3 | import static io.reactivex.android.schedulers.AndroidSchedulers.mainThread;
4 | import static io.reactivex.schedulers.Schedulers.io;
5 |
6 | import android.os.Bundle;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.widget.EditText;
11 |
12 | import com.jakewharton.rxbinding2.internal.Notification;
13 | import com.jakewharton.rxbinding2.widget.RxTextView;
14 | import com.jakewharton.rxrelay2.PublishRelay;
15 | import com.jakewharton.rxrelay2.Relay;
16 | import com.mikepenz.itemanimators.SlideDownAlphaAnimator;
17 |
18 | import java.util.List;
19 |
20 | import butterknife.BindView;
21 | import butterknife.ButterKnife;
22 | import io.reactivex.Observable;
23 |
24 | public class MainActivity extends AppCompatActivity {
25 |
26 | @BindView(R.id.searchquery) EditText searchQueryField;
27 | @BindView(R.id.recyclerview) RecyclerView recyclerView;
28 |
29 | private final Relay