Merge branch 'feature/general_improvements' into master-rx-java-2
# Conflicts: # build.gradle # src/main/java/ru/touchin/roboswag/components/adapters/AdapterDelegate.java # src/main/java/ru/touchin/roboswag/components/adapters/ObservableCollectionAdapter.java
This commit is contained in:
commit
a2b69d64a1
|
|
@ -18,12 +18,11 @@ import ru.touchin.roboswag.components.utils.UiUtils;
|
|||
* Objects of such class controls creation and binding of specific type of RecyclerView's ViewHolders.
|
||||
* Default {@link #getItemViewType} is generating on construction of object.
|
||||
*
|
||||
* @param <TViewHolder> Type of {@link BindableViewHolder} of delegate;
|
||||
* @param <TItem> Type of items to bind to {@link BindableViewHolder}s.
|
||||
* @param <TViewHolder> Type of {@link BindableViewHolder} of delegate.
|
||||
*/
|
||||
@SuppressWarnings("PMD.TooManyMethods")
|
||||
//TooManyMethods: it's ok as it is LifecycleBindable
|
||||
public abstract class AdapterDelegate<TViewHolder extends BindableViewHolder, TItem> implements LifecycleBindable {
|
||||
//TooManyMethods: it's ok
|
||||
public abstract class AdapterDelegate<TViewHolder extends BindableViewHolder> implements LifecycleBindable {
|
||||
|
||||
@NonNull
|
||||
private final LifecycleBindable parentLifecycleBindable;
|
||||
|
|
@ -53,29 +52,6 @@ public abstract class AdapterDelegate<TViewHolder extends BindableViewHolder, TI
|
|||
return defaultItemViewType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if object is processable by this delegate.
|
||||
* This item will be casted to {@link TItem} and passes to {@link #onBindViewHolder(TViewHolder, TItem, int, int)}.
|
||||
*
|
||||
* @param item Item to check;
|
||||
* @param adapterPosition Position of item in adapter;
|
||||
* @param itemCollectionPosition Position of item in collection that contains item;
|
||||
* @return True if item is processable by this delegate.
|
||||
*/
|
||||
public abstract boolean isForViewType(@NonNull final Object item, final int adapterPosition, final int itemCollectionPosition);
|
||||
|
||||
/**
|
||||
* Returns unique ID of item to support stable ID's logic of RecyclerView's adapter.
|
||||
*
|
||||
* @param item Item to check;
|
||||
* @param adapterPosition Position of item in adapter;
|
||||
* @param itemCollectionPosition Position of item in collection that contains item;
|
||||
* @return Unique item ID.
|
||||
*/
|
||||
public long getItemId(@NonNull final TItem item, final int adapterPosition, final int itemCollectionPosition) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates ViewHolder to bind item to it later.
|
||||
*
|
||||
|
|
@ -85,31 +61,6 @@ public abstract class AdapterDelegate<TViewHolder extends BindableViewHolder, TI
|
|||
@NonNull
|
||||
public abstract TViewHolder onCreateViewHolder(@NonNull final ViewGroup parent);
|
||||
|
||||
/**
|
||||
* Binds item to created by this object ViewHolder.
|
||||
*
|
||||
* @param holder ViewHolder to bind item to;
|
||||
* @param item Item to check;
|
||||
* @param adapterPosition Position of item in adapter;
|
||||
* @param itemCollectionPosition Position of item in collection that contains item;
|
||||
*/
|
||||
public abstract void onBindViewHolder(@NonNull final TViewHolder holder, @NonNull final TItem item,
|
||||
final int adapterPosition, final int itemCollectionPosition);
|
||||
|
||||
/**
|
||||
* Binds item with payloads to created by this object ViewHolder.
|
||||
*
|
||||
* @param holder ViewHolder to bind item to;
|
||||
* @param item Item to check;
|
||||
* @param payloads Payloads;
|
||||
* @param adapterPosition Position of item in adapter;
|
||||
* @param itemCollectionPosition Position of item in collection that contains item;
|
||||
*/
|
||||
public void onBindViewHolder(@NonNull final TViewHolder holder, @NonNull final TItem item, @NonNull final List<Object> payloads,
|
||||
final int adapterPosition, final int itemCollectionPosition) {
|
||||
//do nothing by default
|
||||
}
|
||||
|
||||
@SuppressWarnings("CPD-START")
|
||||
//CPD: it is same as in other implementation based on BaseLifecycleBindable
|
||||
@NonNull
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
package ru.touchin.roboswag.components.adapters;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ru.touchin.roboswag.components.utils.LifecycleBindable;
|
||||
|
||||
/**
|
||||
* Objects of such class controls creation and binding of specific type of RecyclerView's ViewHolders.
|
||||
* Such delegates are creating and binding ViewHolders for specific items.
|
||||
* Default {@link #getItemViewType} is generating on construction of object.
|
||||
*
|
||||
* @param <TViewHolder> Type of {@link BindableViewHolder} of delegate;
|
||||
* @param <TItem> Type of items to bind to {@link BindableViewHolder}s.
|
||||
*/
|
||||
public abstract class ItemAdapterDelegate<TViewHolder extends BindableViewHolder, TItem> extends AdapterDelegate<TViewHolder> {
|
||||
|
||||
public ItemAdapterDelegate(@NonNull final LifecycleBindable parentLifecycleBindable) {
|
||||
super(parentLifecycleBindable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if object is processable by this delegate.
|
||||
* This item will be casted to {@link TItem} and passes to {@link #onBindViewHolder(TViewHolder, TItem, int, int)}.
|
||||
*
|
||||
* @param item Item to check;
|
||||
* @param positionInAdapter Position of item in adapter;
|
||||
* @param itemCollectionPosition Position of item in collection that contains item;
|
||||
* @return True if item is processable by this delegate.
|
||||
*/
|
||||
public abstract boolean isForViewType(@NonNull final Object item, final int positionInAdapter, final int itemCollectionPosition);
|
||||
|
||||
/**
|
||||
* Returns unique ID of item to support stable ID's logic of RecyclerView's adapter.
|
||||
*
|
||||
* @param item Item to check;
|
||||
* @param positionInAdapter Position of item in adapter;
|
||||
* @param positionInCollection Position of item in collection that contains item;
|
||||
* @return Unique item ID.
|
||||
*/
|
||||
public long getItemId(@NonNull final TItem item, final int positionInAdapter, final int positionInCollection) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates ViewHolder to bind item to it later.
|
||||
*
|
||||
* @param parent Container of ViewHolder's view.
|
||||
* @return New ViewHolder.
|
||||
*/
|
||||
@NonNull
|
||||
public abstract TViewHolder onCreateViewHolder(@NonNull final ViewGroup parent);
|
||||
|
||||
/**
|
||||
* Binds item to created by this object ViewHolder.
|
||||
*
|
||||
* @param holder ViewHolder to bind item to;
|
||||
* @param item Item to check;
|
||||
* @param positionInAdapter Position of item in adapter;
|
||||
* @param positionInCollection Position of item in collection that contains item;
|
||||
*/
|
||||
public abstract void onBindViewHolder(@NonNull final TViewHolder holder, @NonNull final TItem item,
|
||||
final int positionInAdapter, final int positionInCollection);
|
||||
|
||||
/**
|
||||
* Binds item with payloads to created by this object ViewHolder.
|
||||
*
|
||||
* @param holder ViewHolder to bind item to;
|
||||
* @param item Item to check;
|
||||
* @param payloads Payloads;
|
||||
* @param positionInAdapter Position of item in adapter;
|
||||
* @param positionInCollection Position of item in collection that contains item;
|
||||
*/
|
||||
public void onBindViewHolder(@NonNull final TViewHolder holder, @NonNull final TItem item, @NonNull final List<Object> payloads,
|
||||
final int positionInAdapter, final int positionInCollection) {
|
||||
//do nothing by default
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -30,6 +30,8 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
|
@ -56,12 +58,22 @@ import ru.touchin.roboswag.core.utils.ShouldNotHappenException;
|
|||
* @param <TItem> Type of items to bind to ViewHolders;
|
||||
* @param <TItemViewHolder> Type of ViewHolders to show items.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "PMD.TooManyMethods"})
|
||||
//TooManyMethods: it's ok
|
||||
public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends BindableViewHolder>
|
||||
extends RecyclerView.Adapter<BindableViewHolder> {
|
||||
|
||||
private static final int PRE_LOADING_COUNT = 20;
|
||||
|
||||
private static boolean inDebugMode;
|
||||
|
||||
/**
|
||||
* Enables debugging features like checking concurrent delegates.
|
||||
*/
|
||||
public static void setInDebugMode() {
|
||||
inDebugMode = true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private final BehaviorSubject<Optional<ObservableCollection<TItem>>> observableCollectionSubject
|
||||
= BehaviorSubject.createDefault(new Optional<>(null));
|
||||
|
|
@ -80,7 +92,7 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
@NonNull
|
||||
private final List<RecyclerView> attachedRecyclerViews = new LinkedList<>();
|
||||
@NonNull
|
||||
private final List<AdapterDelegate<TItemViewHolder, TItem>> delegates = new ArrayList<>();
|
||||
private final List<AdapterDelegate<? extends BindableViewHolder>> delegates = new ArrayList<>();
|
||||
|
||||
public ObservableCollectionAdapter(@NonNull final LifecycleBindable lifecycleBindable) {
|
||||
super();
|
||||
|
|
@ -302,23 +314,38 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
* @return List of {@link AdapterDelegate}.
|
||||
*/
|
||||
@NonNull
|
||||
public List<AdapterDelegate<TItemViewHolder, TItem>> getDelegates() {
|
||||
public List<AdapterDelegate<? extends BindableViewHolder>> getDelegates() {
|
||||
return Collections.unmodifiableList(delegates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link AdapterDelegate} to adapter.
|
||||
* Adds {@link ItemAdapterDelegate} to adapter.
|
||||
*
|
||||
* @param delegate Delegate to add.
|
||||
*/
|
||||
public void addDelegate(@NonNull final AdapterDelegate<? extends TItemViewHolder, ? extends TItem> delegate) {
|
||||
for (final AdapterDelegate addedDelegate : delegates) {
|
||||
if (addedDelegate.getItemViewType() == delegate.getItemViewType()) {
|
||||
Lc.assertion("AdapterDelegate with viewType=" + delegate.getItemViewType() + " already added");
|
||||
return;
|
||||
public void addDelegate(@NonNull final ItemAdapterDelegate<? extends TItemViewHolder, ? extends TItem> delegate) {
|
||||
addDelegateInternal(delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link PositionAdapterDelegate} to adapter.
|
||||
*
|
||||
* @param delegate Delegate to add.
|
||||
*/
|
||||
public void addDelegate(@NonNull final PositionAdapterDelegate<? extends BindableViewHolder> delegate) {
|
||||
addDelegateInternal(delegate);
|
||||
}
|
||||
|
||||
private void addDelegateInternal(@NonNull final AdapterDelegate<? extends BindableViewHolder> delegate) {
|
||||
if (inDebugMode) {
|
||||
for (final AdapterDelegate addedDelegate : delegates) {
|
||||
if (addedDelegate.getItemViewType() == delegate.getItemViewType()) {
|
||||
Lc.assertion("AdapterDelegate with viewType=" + delegate.getItemViewType() + " already added");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
delegates.add((AdapterDelegate<TItemViewHolder, TItem>) delegate);
|
||||
delegates.add(delegate);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
|
@ -327,41 +354,88 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
*
|
||||
* @param delegate Delegate to remove.
|
||||
*/
|
||||
public void removeDelegate(@NonNull final AdapterDelegate<? extends TItemViewHolder, ? extends TItem> delegate) {
|
||||
delegates.remove((AdapterDelegate<TItemViewHolder, TItem>) delegate);
|
||||
public void removeDelegate(@NonNull final AdapterDelegate<? extends BindableViewHolder> delegate) {
|
||||
delegates.remove(delegate);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void checkDelegates(@Nullable final AdapterDelegate alreadyPickedDelegate, @NonNull final AdapterDelegate currentDelegate) {
|
||||
if (alreadyPickedDelegate != null) {
|
||||
throw new ShouldNotHappenException("Concurrent delegates: " + currentDelegate + " and " + alreadyPickedDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
private int getItemPositionInCollection(final int positionInAdapter) {
|
||||
final int shiftedPosition = positionInAdapter - getHeadersCount();
|
||||
return shiftedPosition >= 0 && shiftedPosition < innerCollection.size() ? shiftedPosition : -1;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ModifiedCyclomaticComplexity", "PMD.StdCyclomaticComplexity", "PMD.NPathComplexity"})
|
||||
//Complexity: because of debug code
|
||||
@Override
|
||||
public int getItemViewType(final int positionInAdapter) {
|
||||
final int positionInCollection = positionInAdapter - getHeadersCount();
|
||||
if (positionInCollection < 0 || positionInCollection >= innerCollection.size()) {
|
||||
return super.getItemViewType(positionInAdapter);
|
||||
}
|
||||
final TItem item = innerCollection.get(positionInCollection);
|
||||
for (final AdapterDelegate<?, TItem> delegate : delegates) {
|
||||
if (delegate.isForViewType(item, positionInAdapter, positionInCollection)) {
|
||||
return delegate.getItemViewType();
|
||||
AdapterDelegate delegateOfViewType = null;
|
||||
final int positionInCollection = getItemPositionInCollection(positionInAdapter);
|
||||
final TItem item = positionInCollection >= 0 ? innerCollection.get(positionInCollection) : null;
|
||||
for (final AdapterDelegate<?> delegate : delegates) {
|
||||
if (delegate instanceof ItemAdapterDelegate) {
|
||||
if (item != null && ((ItemAdapterDelegate) delegate).isForViewType(item, positionInAdapter, positionInCollection)) {
|
||||
checkDelegates(delegateOfViewType, delegate);
|
||||
delegateOfViewType = delegate;
|
||||
if (!inDebugMode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (delegate instanceof PositionAdapterDelegate) {
|
||||
if (((PositionAdapterDelegate) delegate).isForViewType(positionInAdapter)) {
|
||||
checkDelegates(delegateOfViewType, delegate);
|
||||
delegateOfViewType = delegate;
|
||||
if (!inDebugMode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Lc.assertion("Delegate of type " + delegate.getClass());
|
||||
}
|
||||
}
|
||||
return super.getItemViewType(positionInAdapter);
|
||||
|
||||
return delegateOfViewType != null ? delegateOfViewType.getItemViewType() : super.getItemViewType(positionInAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(final int positionInAdapter) {
|
||||
final int positionInCollection = positionInAdapter - getHeadersCount();
|
||||
if (positionInCollection < 0 || positionInCollection >= innerCollection.size()) {
|
||||
return super.getItemId(positionInAdapter);
|
||||
}
|
||||
final LongContainer result = new LongContainer();
|
||||
tryDelegateAction(positionInAdapter,
|
||||
(itemAdapterDelegate, positionInCollection) ->
|
||||
result.value = itemAdapterDelegate.getItemId(innerCollection.get(positionInCollection),
|
||||
positionInAdapter, positionInCollection),
|
||||
positionAdapterDelegate -> result.value = positionAdapterDelegate.getItemId(positionInAdapter),
|
||||
(positionInCollection) -> result.value = super.getItemId(positionInAdapter));
|
||||
return result.value;
|
||||
}
|
||||
|
||||
final int itemViewType = getItemViewType(positionInAdapter);
|
||||
final TItem item = innerCollection.get(positionInCollection);
|
||||
for (final AdapterDelegate<?, TItem> delegate : delegates) {
|
||||
if (delegate.getItemViewType() == itemViewType) {
|
||||
return delegate.getItemId(item, positionInAdapter, positionInCollection);
|
||||
private void tryDelegateAction(final int positionInAdapter,
|
||||
@NonNull final BiConsumer<ItemAdapterDelegate, Integer> itemAdapterDelegateAction,
|
||||
@NonNull final Consumer<PositionAdapterDelegate> positionAdapterDelegateAction,
|
||||
@NonNull final Consumer<Integer> defaultAction) {
|
||||
final int viewType = getItemViewType(positionInAdapter);
|
||||
final int positionInCollection = getItemPositionInCollection(positionInAdapter);
|
||||
for (final AdapterDelegate<?> delegate : delegates) {
|
||||
if (delegate instanceof ItemAdapterDelegate) {
|
||||
if (positionInCollection >= 0 && viewType == delegate.getItemViewType()) {
|
||||
itemAdapterDelegateAction.accept((ItemAdapterDelegate) delegate, positionInCollection);
|
||||
return;
|
||||
}
|
||||
} else if (delegate instanceof PositionAdapterDelegate) {
|
||||
if (viewType == delegate.getItemViewType()) {
|
||||
positionAdapterDelegateAction.accept((PositionAdapterDelegate) delegate);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Lc.assertion("Delegate of type " + delegate.getClass());
|
||||
}
|
||||
}
|
||||
return super.getItemId(positionInAdapter);
|
||||
defaultAction.accept(positionInCollection);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -372,7 +446,7 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
@NonNull
|
||||
@Override
|
||||
public BindableViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
||||
for (final AdapterDelegate<?, TItem> delegate : delegates) {
|
||||
for (final AdapterDelegate<?> delegate : delegates) {
|
||||
if (delegate.getItemViewType() == viewType) {
|
||||
return delegate.onCreateViewHolder(parent);
|
||||
}
|
||||
|
|
@ -384,26 +458,40 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
public void onBindViewHolder(@NonNull final BindableViewHolder holder, final int positionInAdapter) {
|
||||
lastUpdatedChangeNumber = innerCollection.getChangesCount();
|
||||
|
||||
final int positionInCollection = positionInAdapter - getHeadersCount();
|
||||
if (positionInCollection < 0 || positionInCollection >= innerCollection.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateMoreAutoLoadingRequest(positionInCollection);
|
||||
bindItemViewHolder(holder, null, positionInAdapter, positionInCollection);
|
||||
tryDelegateAction(positionInAdapter,
|
||||
(itemAdapterDelegate, positionInCollection) -> {
|
||||
bindItemViewHolder(itemAdapterDelegate, holder, innerCollection.get(positionInCollection),
|
||||
null, positionInAdapter, positionInCollection);
|
||||
updateMoreAutoLoadingRequest(positionInCollection);
|
||||
},
|
||||
positionAdapterDelegate -> positionAdapterDelegate.onBindViewHolder(holder, positionInAdapter),
|
||||
(positionInCollection) -> {
|
||||
if (positionInCollection >= 0) {
|
||||
bindItemViewHolder(null, holder, innerCollection.get(positionInCollection), null, positionInAdapter, positionInCollection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final BindableViewHolder holder, final int positionInAdapter, @NonNull final List<Object> payloads) {
|
||||
super.onBindViewHolder(holder, positionInAdapter, payloads);
|
||||
final int positionInCollection = positionInAdapter - getHeadersCount();
|
||||
if (positionInCollection < 0 || positionInCollection >= innerCollection.size()) {
|
||||
return;
|
||||
}
|
||||
bindItemViewHolder(holder, payloads, positionInAdapter, positionInCollection);
|
||||
tryDelegateAction(positionInAdapter,
|
||||
(itemAdapterDelegate, positionInCollection) -> {
|
||||
bindItemViewHolder(itemAdapterDelegate, holder, innerCollection.get(positionInCollection),
|
||||
payloads, positionInAdapter, positionInCollection);
|
||||
updateMoreAutoLoadingRequest(positionInCollection);
|
||||
},
|
||||
positionAdapterDelegate -> positionAdapterDelegate.onBindViewHolder(holder, positionInAdapter),
|
||||
(positionInCollection) -> {
|
||||
if (positionInCollection >= 0) {
|
||||
bindItemViewHolder(null, holder, innerCollection.get(positionInCollection),
|
||||
payloads, positionInAdapter, positionInCollection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void bindItemViewHolder(@NonNull final BindableViewHolder holder, @Nullable final List<Object> payloads,
|
||||
private void bindItemViewHolder(@Nullable final ItemAdapterDelegate<TItemViewHolder, TItem> itemAdapterDelegate,
|
||||
@NonNull final BindableViewHolder holder, @NonNull final TItem item, @Nullable final List<Object> payloads,
|
||||
final int positionInAdapter, final int positionInCollection) {
|
||||
final TItemViewHolder itemViewHolder;
|
||||
try {
|
||||
|
|
@ -412,24 +500,19 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
Lc.assertion(exception);
|
||||
return;
|
||||
}
|
||||
final TItem item = innerCollection.get(positionInCollection);
|
||||
final int itemViewType = getItemViewType(positionInAdapter);
|
||||
|
||||
updateClickListener(holder, item, positionInAdapter, positionInCollection);
|
||||
for (final AdapterDelegate<TItemViewHolder, TItem> delegate : delegates) {
|
||||
if (itemViewType == delegate.getItemViewType()) {
|
||||
if (payloads == null) {
|
||||
delegate.onBindViewHolder(itemViewHolder, item, positionInAdapter, positionInCollection);
|
||||
} else {
|
||||
delegate.onBindViewHolder(itemViewHolder, item, payloads, positionInAdapter, positionInCollection);
|
||||
}
|
||||
return;
|
||||
if (itemAdapterDelegate != null) {
|
||||
if (payloads == null) {
|
||||
itemAdapterDelegate.onBindViewHolder(itemViewHolder, item, positionInAdapter, positionInCollection);
|
||||
} else {
|
||||
itemAdapterDelegate.onBindViewHolder(itemViewHolder, item, payloads, positionInAdapter, positionInCollection);
|
||||
}
|
||||
}
|
||||
if (payloads == null) {
|
||||
onBindItemToViewHolder(itemViewHolder, positionInAdapter, item);
|
||||
} else {
|
||||
onBindItemToViewHolder(itemViewHolder, positionInAdapter, item, payloads);
|
||||
if (payloads == null) {
|
||||
onBindItemToViewHolder(itemViewHolder, positionInAdapter, item);
|
||||
} else {
|
||||
onBindItemToViewHolder(itemViewHolder, positionInAdapter, item, payloads);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -467,7 +550,7 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
* @param item Item returned by position (WITH HEADER OFFSET!).
|
||||
*/
|
||||
protected void onBindItemToViewHolder(@NonNull final TItemViewHolder holder, final int positionInAdapter, @NonNull final TItem item) {
|
||||
//do nothing by default
|
||||
// do nothing by default - let delegates do it
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -481,13 +564,13 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
*/
|
||||
protected void onBindItemToViewHolder(@NonNull final TItemViewHolder holder, final int positionInAdapter, @NonNull final TItem item,
|
||||
@NonNull final List<Object> payloads) {
|
||||
// do nothing by default
|
||||
// do nothing by default - let delegates do it
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TItem getItem(final int positionInAdapter) {
|
||||
final int positionInCollection = positionInAdapter - getHeadersCount();
|
||||
return positionInCollection < 0 || positionInCollection >= innerCollection.size() ? null : innerCollection.get(positionInCollection);
|
||||
final int positionInCollection = getItemPositionInCollection(positionInAdapter);
|
||||
return positionInCollection >= 0 ? innerCollection.get(positionInCollection) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -578,4 +661,10 @@ public abstract class ObservableCollectionAdapter<TItem, TItemViewHolder extends
|
|||
|
||||
}
|
||||
|
||||
private class LongContainer {
|
||||
|
||||
private long value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
package ru.touchin.roboswag.components.adapters;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ru.touchin.roboswag.components.utils.LifecycleBindable;
|
||||
|
||||
/**
|
||||
* Objects of such class controls creation and binding of specific type of RecyclerView's ViewHolders.
|
||||
* Such delegates are creating and binding ViewHolders by position in adapter.
|
||||
* Default {@link #getItemViewType} is generating on construction of object.
|
||||
*
|
||||
* @param <TViewHolder> Type of {@link BindableViewHolder} of delegate.
|
||||
*/
|
||||
public abstract class PositionAdapterDelegate<TViewHolder extends BindableViewHolder> extends AdapterDelegate<TViewHolder> {
|
||||
|
||||
public PositionAdapterDelegate(@NonNull final LifecycleBindable parentLifecycleBindable) {
|
||||
super(parentLifecycleBindable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if object is processable by this delegate.
|
||||
*
|
||||
* @param positionInAdapter Position of item in adapter;
|
||||
* @return True if item is processable by this delegate.
|
||||
*/
|
||||
public abstract boolean isForViewType(final int positionInAdapter);
|
||||
|
||||
/**
|
||||
* Returns unique ID of item to support stable ID's logic of RecyclerView's adapter.
|
||||
*
|
||||
* @param positionInAdapter Position of item in adapter;
|
||||
* @return Unique item ID.
|
||||
*/
|
||||
public long getItemId(final int positionInAdapter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates ViewHolder to bind position to it later.
|
||||
*
|
||||
* @param parent Container of ViewHolder's view.
|
||||
* @return New ViewHolder.
|
||||
*/
|
||||
@NonNull
|
||||
public abstract TViewHolder onCreateViewHolder(@NonNull final ViewGroup parent);
|
||||
|
||||
/**
|
||||
* Binds position to ViewHolder.
|
||||
*
|
||||
* @param holder ViewHolder to bind position to;
|
||||
* @param positionInAdapter Position of item in adapter.
|
||||
*/
|
||||
public abstract void onBindViewHolder(@NonNull final TViewHolder holder, final int positionInAdapter);
|
||||
|
||||
/**
|
||||
* Binds position with payloads to ViewHolder.
|
||||
*
|
||||
* @param holder ViewHolder to bind position to;
|
||||
* @param payloads Payloads;
|
||||
* @param positionInAdapter Position of item in adapter.
|
||||
*/
|
||||
public void onBindViewHolder(@NonNull final TViewHolder holder, @NonNull final List<Object> payloads, final int positionInAdapter) {
|
||||
//do nothing by default
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -44,6 +44,8 @@ public class SimpleActionBarDrawerToggle extends ActionBarDrawerToggle
|
|||
@NonNull
|
||||
private final View sidebar;
|
||||
|
||||
private boolean isInvalidateOptionsMenuSupported = true;
|
||||
|
||||
private boolean hamburgerShowed;
|
||||
private boolean sidebarDisabled;
|
||||
|
||||
|
|
@ -203,7 +205,9 @@ public class SimpleActionBarDrawerToggle extends ActionBarDrawerToggle
|
|||
|
||||
@Override
|
||||
public void onDrawerClosed(@NonNull final View view) {
|
||||
activity.supportInvalidateOptionsMenu();
|
||||
if (isInvalidateOptionsMenuSupported) {
|
||||
activity.supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -218,7 +222,18 @@ public class SimpleActionBarDrawerToggle extends ActionBarDrawerToggle
|
|||
@Override
|
||||
public void onDrawerOpened(@NonNull final View drawerView) {
|
||||
activity.hideSoftInput();
|
||||
activity.supportInvalidateOptionsMenu();
|
||||
if (isInvalidateOptionsMenuSupported) {
|
||||
activity.supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set turn on/off invocation of supportInvalidateOptionsMenu
|
||||
*
|
||||
* @param isInvalidateOptionsMenuSupported flag for turning on/off invocation.
|
||||
*/
|
||||
public void setInvalidateOptionsMenuSupported(final boolean isInvalidateOptionsMenuSupported) {
|
||||
this.isInvalidateOptionsMenuSupported = isInvalidateOptionsMenuSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue