diff --git a/src/main/java/ru/touchin/roboswag/components/listing/adapters/ObservableCollectionAdapter.java b/src/main/java/ru/touchin/roboswag/components/listing/adapters/ObservableCollectionAdapter.java index f3abb6d..61500d5 100644 --- a/src/main/java/ru/touchin/roboswag/components/listing/adapters/ObservableCollectionAdapter.java +++ b/src/main/java/ru/touchin/roboswag/components/listing/adapters/ObservableCollectionAdapter.java @@ -19,12 +19,14 @@ package ru.touchin.roboswag.components.listing.adapters; +import android.os.Looper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -50,6 +52,28 @@ public abstract class ObservableCollectionAdapter Collection simpleChanges(@Nullable final ObservableCollection oldCollection, + @Nullable final ObservableCollection newCollection, + final int offset) { + final int oldSize = getNullableCollectionSize(oldCollection); + final int newSize = getNullableCollectionSize(newCollection); + final List result = new ArrayList<>(); + if (oldSize < newSize) { + result.add(new Change(Change.Type.INSERTED, oldSize + offset, newSize - oldSize)); + } else if (newSize > oldSize) { + result.add(new Change(Change.Type.REMOVED, newSize + offset, oldSize - newSize)); + } + if (newSize != 0 && oldSize != 0) { + result.add(new Change(Change.Type.CHANGED, offset, Math.min(oldSize, newSize))); + } + return result; + } + @NonNull private final UiBindable uiBindable; @Nullable @@ -58,17 +82,18 @@ public abstract class ObservableCollectionAdapter observableCollection; @Nullable private Subscription itemsProviderSubscription; - - @NonNull - public UiBindable getUiBindable() { - return uiBindable; - } + private int lastUpdatedChangeNumber; public ObservableCollectionAdapter(@NonNull final UiBindable uiBindable) { super(); this.uiBindable = uiBindable; } + @NonNull + public UiBindable getUiBindable() { + return uiBindable; + } + protected long getItemClickDelay() { return UiUtils.RIPPLE_EFFECT_DELAY; } @@ -91,15 +116,34 @@ public abstract class ObservableCollectionAdapter changes = simpleChanges(this.observableCollection, observableCollection, itemsOffset()); this.observableCollection = observableCollection; - notifyDataSetChanged(); + if (!changes.isEmpty()) { + notifyAboutChanges(changes); + } if (this.observableCollection != null) { itemsProviderSubscription = uiBindable.bind(this.observableCollection.observeChanges()) .subscribe(this::onItemsChanged); } } - protected void onItemsChanged(@NonNull final Collection changes) { + protected void onItemsChanged(@NonNull final ObservableCollection.CollectionChange collectionChange) { + if (observableCollection == null) { + return; + } + if (Looper.myLooper() != Looper.getMainLooper()) { + Lc.assertion("Items changes called on not main thread"); + return; + } + if (collectionChange.getNumber() != observableCollection.getChangesCount() + || collectionChange.getNumber() != lastUpdatedChangeNumber + 1) { + notifyDataSetChanged(); + return; + } + notifyAboutChanges(collectionChange.getChanges()); + } + + private void notifyAboutChanges(@NonNull final Collection changes) { for (final Change change : changes) { switch (change.getType()) { case INSERTED: @@ -120,7 +164,9 @@ public abstract class ObservableCollectionAdapter onItemClickListener) { this.onItemClickListener = onItemClickListener; - notifyDataSetChanged(); + if (observableCollection != null && !observableCollection.isEmpty()) { + notifyItemRangeChanged(itemsOffset(), observableCollection.size()); + } } @Override @@ -142,6 +188,7 @@ public abstract class ObservableCollectionAdapter