Observable lists in release candidate state

This commit is contained in:
Gavriil Sitnikov 2016-08-29 00:17:21 +03:00
parent 6c68ccfdc5
commit f5950841b4
13 changed files with 456 additions and 25 deletions

View File

@ -26,8 +26,24 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* Class representing simple change of collection like insertion, remove or replacing/changing items.
*
* @param <TItem> Type of changing collection's items.
*/
public class Change<TItem> {
/**
* Method to calculate changes between two collections.
*
* @param initialCollection Initial collection;
* @param modifiedCollection Changed collection;
* @param shrinkChangesToModifiedSize Flag to make position of changed items be less then modified collection size.
* It is needed sometimes to not get exceptions like {@link ArrayIndexOutOfBoundsException}.
* @param <TItem> Type of collections items.
* @return Changes between collections.
*/
@NonNull
public static <TItem> Collection<Change<TItem>> calculateCollectionChanges(@NonNull final Collection<TItem> initialCollection,
@NonNull final Collection<TItem> modifiedCollection,
@ -49,20 +65,40 @@ public class Change<TItem> {
this.count = changedItems.size();
}
/**
* Returns type of change.
*
* @return Type of change.
*/
@NonNull
public Type getType() {
return type;
}
/**
* Returns collection of items which this change applied to.
*
* @return Changed items.
*/
@NonNull
public Collection<TItem> getChangedItems() {
return changedItems;
}
/**
* Returns first index of changed item.
*
* @return Start of change.
*/
public int getStart() {
return start;
}
/**
* Returns count of changed items.
*
* @return Count of changed items.
*/
public int getCount() {
return count;
}
@ -72,6 +108,9 @@ public class Change<TItem> {
return type + " change of " + start + ":" + count;
}
/**
* Type of change.
*/
public enum Type {
INSERTED,
CHANGED,

View File

@ -36,7 +36,12 @@ import rx.Subscriber;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* TODO: description
* Class to represent collection which is providing it's inner changes in Rx observable way.
* Use {@link #observeChanges()} and {@link #observeItems()} to observe collection changes.
* Use {@link #loadItem(int)} to load item asynchronously.
* Methods {@link #size()} and {@link #get(int)} will return only already loaded items info.
*
* @param <TItem> Type of collection's items.
*/
public abstract class ObservableCollection<TItem> implements Serializable {
@ -73,14 +78,29 @@ public abstract class ObservableCollection<TItem> implements Serializable {
.refCount();
}
/**
* Return changes count number since collection creation.
*
* @return Changes count.
*/
public int getChangesCount() {
return changesCount;
}
/**
* Method to notify that collection have changed.
*
* @param change Change of collection.
*/
protected void notifyAboutChange(@NonNull final Change<TItem> change) {
notifyAboutChanges(Collections.singleton(change));
}
/**
* Method to notify that collection have changed.
*
* @param changes Changes of collection.
*/
protected void notifyAboutChanges(@NonNull final Collection<Change<TItem>> changes) {
changesCount++;
if (changesSubscriber != null) {
@ -88,31 +108,80 @@ public abstract class ObservableCollection<TItem> implements Serializable {
}
}
/**
* Observes changes so it can be used to update UI based on changes etc.
*
* @return List of changes applied to collection.
*/
@NonNull
public Observable<CollectionChange<TItem>> observeChanges() {
return changesObservable;
}
/**
* Returns already loaded item by position.
* Use it carefully for collections which are loading asynchronously.
*
* @param position Position of item to get;
* @return Item in collection by position.
*/
@NonNull
public abstract TItem get(int position);
/**
* Returns already loaded items.
* Use it carefully for collections which are loading asynchronously.
*
* @return Collection of items.
*/
@NonNull
public abstract Collection<TItem> getItems();
/**
* Returns {@link Observable} to observe items collection.
* Collection returned in onNext is not inner collection but it's copy, actually so you can't modify it.
*
* @return Collection's {@link Observable}.
*/
@NonNull
public Observable<Collection<TItem>> observeItems() {
return itemsObservable;
}
/**
* Returns size of already loaded items.
*
* @return Size.
*/
public abstract int size();
/**
* Returns if already loaded items are empty or not.
*
* @return True if items are empty.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns {@link Observable} which is loading item by position.
* It could return null in onNext callback if there is no item to load for such position.
*
* @param position Position to load item;
* @return {@link Observable} to load item.
*/
@NonNull
public abstract Observable<TItem> loadItem(int position);
/**
* Returns {@link Observable} which is loading item by range.
* It will return collection of loaded items in onNext callback.
*
* @param first First position of item to load;
* @param last Last position of item to load;
* @return {@link Observable} to load items.
*/
@NonNull
public Observable<Collection<TItem>> loadRange(final int first, final int last) {
final List<Observable<TItem>> itemsRequests = new ArrayList<>();
@ -135,6 +204,11 @@ public abstract class ObservableCollection<TItem> implements Serializable {
this.itemsObservable = createItemsObservable();
}
/**
* Class which is representing change of collection. There could be multiple changes applied to collection.
*
* @param <TItem> Type of collection's items.
*/
public static class CollectionChange<TItem> {
private final int number;
@ -146,10 +220,20 @@ public abstract class ObservableCollection<TItem> implements Serializable {
this.changes = changes;
}
/**
* Returns number of change.
*
* @return Number of change.
*/
public int getNumber() {
return number;
}
/**
* Returns collection of changes.
*
* @return Collection of changes.
*/
@NonNull
public Collection<Change<TItem>> getChanges() {
return changes;

View File

@ -14,7 +14,10 @@ import rx.functions.Func1;
/**
* Created by Gavriil Sitnikov on 02/06/2016.
* TODO: fill description
* {@link ObservableCollection} based on simple collection with filter inside.
* Changing filter or collection will provide changes from {@link #observeChanges()}.
*
* @param <TItem> Type of collection's items.
*/
public class ObservableFilteredList<TItem> extends ObservableCollection<TItem> {
@ -44,7 +47,7 @@ public class ObservableFilteredList<TItem> extends ObservableCollection<TItem> {
public ObservableFilteredList(@NonNull final Collection<TItem> sourceCollection) {
super();
this.sourceCollection = sourceCollection;
this.sourceCollection = new ArrayList<>(sourceCollection);
this.filteredList = new ArrayList<>(sourceCollection);
}
@ -56,16 +59,26 @@ public class ObservableFilteredList<TItem> extends ObservableCollection<TItem> {
public ObservableFilteredList(@NonNull final Collection<TItem> sourceCollection,
@NonNull final Func1<TItem, Boolean> filter) {
super();
this.sourceCollection = sourceCollection;
this.sourceCollection = new ArrayList<>(sourceCollection);
this.filter = filter;
filteredList = filterCollection(this.sourceCollection, this.filter);
}
/**
* Sets collection of items to filter.
*
* @param sourceCollection Collection with items.
*/
public void setSourceCollection(@Nullable final Collection<TItem> sourceCollection) {
this.sourceCollection = sourceCollection;
this.sourceCollection = sourceCollection != null ? new ArrayList<>(sourceCollection) : null;
updateCollections();
}
/**
* Sets filter that should return false as result of call to filter item.
*
* @param filter Function to filter item. True - item will stay, false - item will be filtered.
*/
public void setFilter(@Nullable final Func1<TItem, Boolean> filter) {
this.filter = filter;
updateCollections();

View File

@ -34,7 +34,11 @@ import rx.Observable;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* TODO: description
* {@link ObservableCollection} that is based on list.
* So it is providing similar List's methods like adding/removing/clearing etc.
* But! You can observe it's changes.
*
* @param <TItem> Type of collection's items.
*/
public class ObservableList<TItem> extends ObservableCollection<TItem> implements Serializable {
@ -53,10 +57,21 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
items = new ArrayList<>(initialItems);
}
/**
* Adding item at the end of list.
*
* @param item Item to add.
*/
public void add(@NonNull final TItem item) {
add(items.size(), item);
}
/**
* Adding item at specific list position.
*
* @param position Position to add item to;
* @param item Item to add.
*/
public void add(final int position, @NonNull final TItem item) {
synchronized (this) {
items.add(position, item);
@ -64,10 +79,21 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
}
}
/**
* Adding items at the end of list.
*
* @param itemsToAdd Items to add.
*/
public void addAll(@NonNull final Collection<TItem> itemsToAdd) {
addAll(items.size(), itemsToAdd);
}
/**
* Adding items at specific list position.
*
* @param position Position to add items to;
* @param itemsToAdd Items to add.
*/
public void addAll(final int position, @NonNull final Collection<TItem> itemsToAdd) {
synchronized (this) {
if (!itemsToAdd.isEmpty()) {
@ -77,10 +103,21 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
}
}
/**
* Removing item by position.
*
* @param position Position to remove item from.
*/
public void remove(final int position) {
remove(position, 1);
}
/**
* Removing items by position.
*
* @param position Position to remove items from;
* @param count Count of items to remove.
*/
public void remove(final int position, final int count) {
if (count == 0) {
return;
@ -95,6 +132,9 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
}
}
/**
* Removing all items from list.
*/
public void clear() {
synchronized (this) {
final Change<TItem> change = new Change<>(Change.Type.REMOVED, items, 0);
@ -121,10 +161,22 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
}
}
/**
* Replace item at specific position.
*
* @param position Position to replace item;
* @param item Item to place.
*/
public void update(final int position, @NonNull final TItem item) {
update(position, Collections.singleton(item));
}
/**
* Replace items at specific position.
*
* @param position Position to replace items;
* @param updatedItems Items to place.
*/
public void update(final int position, @NonNull final Collection<TItem> updatedItems) {
if (updatedItems.isEmpty()) {
return;
@ -139,6 +191,11 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
}
}
/**
* Resetting all items in list to new ones.
*
* @param newItems New items to set.
*/
public void set(@NonNull final Collection<TItem> newItems) {
synchronized (this) {
final Collection<Change<TItem>> changes = Change.calculateCollectionChanges(items, newItems, false);
@ -157,6 +214,12 @@ public class ObservableList<TItem> extends ObservableCollection<TItem> implement
}
}
/**
* Returns position of item in list.
*
* @param item Item to find index of;
* @return Position of item in list or -1 if item not found.
*/
public int indexOf(@NonNull final TItem item) {
synchronized (this) {
return items.indexOf(item);

View File

@ -26,17 +26,35 @@ import java.util.Collection;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* TODO: description
* Object represents loaded items with reference to load other parts and info of are there more items to load or not.
*
* @param <TItem> Type of items to load;
* @param <TReference> Type of reference to load other parts of items.
*/
public interface LoadedItems<TItem, TReference> {
int UNKNOWN_ITEMS_COUNT = -1;
/**
* Returns count of items that could be loaded more.
*
* @return Count of items to load more or UNKNOWN_ITEMS_COUNT if it's unknown info.
*/
int getMoreItemsCount();
/**
* Returns loaded items.
*
* @return Loaded items.
*/
@NonNull
Collection<TItem> getItems();
/**
* Returns reference that could be used to load other parts of items.
*
* @return Reference object.
*/
@Nullable
TReference getReference();

View File

@ -23,12 +23,26 @@ import android.support.annotation.Nullable;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* TODO: description
* Object represents loaded items with reference to load other parts and info of are there more items to load or not.
*
* @param <TItem> Type of items to load;
* @param <TReference> Type of reference to load other parts of items;
* @param <TNewerReference> Type of reference to load newer parts of items.
*/
public interface LoadedRenewableItems<TItem, TReference, TNewerReference> extends LoadedItems<TItem, TReference> {
/**
* Returns count of new items other than loaded.
*
* @return Count of new items other than loaded.
*/
int getNewerItemsCount();
/**
* Returns reference to load newer items from this loaded part.
*
* @return Reference to load newer items.
*/
@Nullable
TNewerReference getNewerReference();

View File

@ -43,13 +43,22 @@ import rx.subjects.BehaviorSubject;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* TODO: description
* {@link ObservableCollection} which is loading items more and more by paging/limit-offset/reference-based mechanisms.
* To use this collection {@link MoreItemsLoader} should be created.
* {@link MoreItemsLoader} is an object to load next block of items by info from previous loaded block (last loaded item/reference etc.).
*
* @param <TItem> Type of collection's items;
* @param <TMoreReference> Type of reference object to help rightly loading next block of items;
* @param <TLoadedItems> Type of loading block of items.
*/
public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedItems<TItem, TMoreReference>>
extends ObservableCollection<TItem> {
private static final int RETRY_LOADING_AFTER_CHANGE_COUNT = 5;
private static final LoadedItemsFilter<?> DUPLICATES_REMOVER = (collectionObject, loadedItemsObject) ->
collectionObject.equals(loadedItemsObject) ? FilterAction.REMOVE_FROM_LOADED_ITEMS : FilterAction.DO_NOTHING;
@NonNull
private final Scheduler loaderScheduler = RxAndroidUtils.createLooperScheduler();
@NonNull
@ -58,7 +67,8 @@ public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedI
private final BehaviorSubject<Integer> moreItemsCount = BehaviorSubject.create(LoadedItems.UNKNOWN_ITEMS_COUNT);
@NonNull
private final ObservableList<TItem> innerList = new ObservableList<>();
private boolean removeDuplicates;
@Nullable
private LoadedItemsFilter<TItem> loadedItemsFilter;
@Nullable
private TMoreReference moreItemsReference;
@ -128,39 +138,75 @@ public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedI
Lc.assertion("Illegal operation. Modify getInnerList()");
}
/**
* Returns {@link ObservableList} of already loaded items so you can modify it.
*
* @return {@link ObservableList} of already loaded items.
*/
@NonNull
protected ObservableList<TItem> getInnerList() {
return innerList;
}
/**
* Returns if there are more items to load.
*
* @return True if there are more items to load.
*/
public boolean hasMoreItems() {
return moreItemsCount.getValue() != 0;
}
/**
* Returns {@link Observable} which is providing status of if is there are more items to load or not.
*
* @return {@link Observable} of more items availability status.
*/
@NonNull
public Observable<Boolean> observeHasMoreItems() {
return moreItemsCount.map(count -> count != 0).distinctUntilChanged();
}
/**
* Returns {@link Observable} which is providing count of more items to load.
*
* @return {@link Observable} of more items availability status.
*/
@NonNull
public Observable<Integer> observeMoreItemsCount() {
return moreItemsCount.distinctUntilChanged();
}
public boolean isRemoveDuplicates() {
return removeDuplicates;
/**
* Sets if duplicates (compared by {@link #equals(Object)}) should be removed from loaded part of items right after loading.
*
* @param removeDuplicates True if duplicates should be removed.
*/
@SuppressWarnings("unchecked")
//unchecked: it's OK as we are using private static filter
public void setRemoveDuplicates(final boolean removeDuplicates) {
if (this.loadedItemsFilter != null && this.loadedItemsFilter != DUPLICATES_REMOVER) {
Lc.assertion("Remove old filter manually first");
return;
}
this.loadedItemsFilter = removeDuplicates ? (LoadedItemsFilter<TItem>) DUPLICATES_REMOVER : null;
}
public void setRemoveDuplicates(final boolean removeDuplicates) {
this.removeDuplicates = removeDuplicates;
/**
* Sets specific filter object which will remove items from already loaded part or from new loaded items right after loading.
*
* @param loadedItemsFilter {@link LoadedItemsFilter} to make decision of removing items.
*/
public void setLoadedItemsFilter(@Nullable final LoadedItemsFilter<TItem> loadedItemsFilter) {
this.loadedItemsFilter = loadedItemsFilter;
}
private void innerOnItemsLoaded(@NonNull final TLoadedItems loadedItems, final int insertPosition, final boolean reset) {
final List<TItem> items = new ArrayList<>(loadedItems.getItems());
final boolean lastPage = insertPosition > size() - 1;
if (!reset) {
if (removeDuplicates) {
removeDuplicatesFromList(items);
if (this.loadedItemsFilter != null) {
removeDuplicatesFromList(items, this.loadedItemsFilter);
}
innerList.addAll(insertPosition, items);
} else {
@ -173,17 +219,28 @@ public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedI
}
}
/**
* Calls when any new items part loaded.
*
* @param loadedItems Loaded items;
* @param insertPosition Position to insert loaded items;
* @param reset Flag to reset previously loaded items or not.
*/
protected void onItemsLoaded(@NonNull final TLoadedItems loadedItems, final int insertPosition, final boolean reset) {
innerOnItemsLoaded(loadedItems, insertPosition, reset);
}
private void removeDuplicatesFromList(@NonNull final List<TItem> items) {
private void removeDuplicatesFromList(@NonNull final List<TItem> items, @NonNull final LoadedItemsFilter<TItem> loadedItemsFilter) {
for (int i = items.size() - 1; i >= 0; i--) {
for (int j = 0; j < innerList.size(); j++) {
if (innerList.get(j).equals(items.get(i))) {
for (int j = innerList.size() - 1; j >= 0; j--) {
final FilterAction filterAction = loadedItemsFilter.decideFilterAction(innerList.get(j), items.get(i));
if (filterAction == FilterAction.REMOVE_FROM_LOADED_ITEMS) {
items.remove(i);
break;
}
if (filterAction == FilterAction.REMOVE_FROM_COLLECTION) {
innerList.remove(j);
}
}
}
}
@ -205,6 +262,11 @@ public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedI
return innerList.getItems();
}
/**
* Returns {@link Observable} that is loading new items.
*
* @return {@link Observable} that is loading new items.
*/
@NonNull
protected Observable<TLoadedItems> getLoadingMoreObservable() {
return loadingMoreObservable;
@ -229,11 +291,19 @@ public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedI
.retry((number, throwable) -> throwable instanceof NotLoadedYetException);
}
/**
* Remove all loaded items and resets collection's state.
*/
public void reset() {
innerList.clear();
resetState();
}
/**
* Remove all loaded items and resets collection's state but sets some initial items.
*
* @param initialItems initial items to be set after reset.
*/
public void reset(@NonNull final TLoadedItems initialItems) {
onItemsLoaded(initialItems, 0, true);
}
@ -243,9 +313,44 @@ public class LoadingMoreList<TItem, TMoreReference, TLoadedItems extends LoadedI
moreItemsCount.onNext(LoadedItems.UNKNOWN_ITEMS_COUNT);
}
/**
* Action to do with some items while new part of items have loaded.
*/
public enum FilterAction {
DO_NOTHING,
REMOVE_FROM_COLLECTION,
REMOVE_FROM_LOADED_ITEMS
}
/**
* Class that is representing object to decide what to do with some items from already loaded and newly loaded part.
* It should remove duplicates or items with changed data.
*
* @param <TItem> Type of collection's items.
*/
public interface LoadedItemsFilter<TItem> {
/**
* Returns action to do based on items: do nothing, remove already loaded item or remove newly loaded item.
*
* @param collectionObject Item from collection of already loaded items;
* @param loadedItemsObject Item from collection of newly loaded items part;
* @return Action to do with items.
*/
@NonNull
FilterAction decideFilterAction(@NonNull final TItem collectionObject, @NonNull final TItem loadedItemsObject);
}
/**
* Helper exception happens if {@link #loadItem(int)} called with big index and latest loading items part still not reached such item.
*/
protected static class NotLoadedYetException extends Exception {
}
/**
* Exception happens if loading request changed during loading so loaded items are not actual anymore.
*/
protected static class RequestChangedDuringLoadingException extends Exception {
}

View File

@ -25,6 +25,7 @@ import android.support.annotation.Nullable;
import java.util.NoSuchElementException;
import ru.touchin.roboswag.core.log.Lc;
import ru.touchin.roboswag.core.observables.collections.ObservableCollection;
import ru.touchin.roboswag.core.utils.ShouldNotHappenException;
import rx.Observable;
import rx.exceptions.OnErrorThrowable;
@ -33,7 +34,14 @@ import rx.subjects.BehaviorSubject;
/**
* Created by Gavriil Sitnikov on 23/05/16.
* TODO: description
* {@link ObservableCollection} which is loading items more and more by paging/limit-offset/reference-based mechanisms but also it is providing
* interface to load newer items and info about it's loading availability.
* To use this collection {@link MoreItemsLoader} and {@link NewerItemsLoader} should be created.
*
* @param <TItem> Type of collection's items;
* @param <TReference> Type of reference object to help rightly loading next block of items;
* @param <TNewerReference> Type of reference object to help rightly loading block of newer items;
* @param <TLoadedItems> Type of loading block of items.
*/
public class LoadingRenewableList<TItem, TReference, TNewerReference,
TLoadedItems extends LoadedRenewableItems<TItem, TReference, TNewerReference>>
@ -49,8 +57,6 @@ public class LoadingRenewableList<TItem, TReference, TNewerReference,
@NonNull
private final Observable<TLoadedItems> loadingNewestObservable;
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
//TODO
public LoadingRenewableList(@NonNull final MoreItemsLoader<TItem, TReference, TLoadedItems> moreMoreItemsLoader,
@NonNull final NewerItemsLoader<TItem, TReference, TNewerReference, TLoadedItems> newerItemsLoader) {
super(moreMoreItemsLoader);
@ -58,8 +64,6 @@ public class LoadingRenewableList<TItem, TReference, TNewerReference,
this.loadingNewestObservable = createLoadingNewerObservable(newerItemsLoader, true);
}
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
//TODO
public LoadingRenewableList(@NonNull final MoreItemsLoader<TItem, TReference, TLoadedItems> moreMoreItemsLoader,
@NonNull final NewerItemsLoader<TItem, TReference, TNewerReference, TLoadedItems> newerItemsLoader,
@Nullable final TLoadedItems initialItems) {
@ -113,15 +117,30 @@ public class LoadingRenewableList<TItem, TReference, TNewerReference,
.refCount();
}
/**
* Returns if there are new items to load.
*
* @return True if there are more items to load.
*/
public boolean hasNewerItems() {
return newerItemsCount.getValue() != 0;
}
/**
* Returns {@link Observable} which is providing status of if is there are new items to load or not.
*
* @return {@link Observable} of more items availability status.
*/
@NonNull
public Observable<Boolean> observeHasNewerItems() {
return newerItemsCount.map(count -> count != 0).distinctUntilChanged();
}
/**
* Returns {@link Observable} which is providing count of new items to load.
*
* @return {@link Observable} of new items availability status.
*/
@NonNull
public Observable<Integer> observeNewerItemsCount() {
return newerItemsCount.distinctUntilChanged();
@ -135,6 +154,12 @@ public class LoadingRenewableList<TItem, TReference, TNewerReference,
}
}
/**
* Calls when newer items part loaded.
*
* @param loadedItems Loaded items;
* @param renew Flag indicates is it loading just to load some new items or to load specific part of new items.
*/
protected void onNewerItemsLoaded(@NonNull final TLoadedItems loadedItems, final boolean renew) {
updateNewerReference(loadedItems);
}
@ -146,11 +171,22 @@ public class LoadingRenewableList<TItem, TReference, TNewerReference,
newerItemsCount.onNext(LoadedItems.UNKNOWN_ITEMS_COUNT);
}
/**
* Returns {@link Observable} that will load newer items by count returned by last loaded items part.
*
* @return {@link Observable} to load newer items.
*/
@NonNull
public Observable<TLoadedItems> loadNewer() {
return loadingNewerObservable;
}
/**
* Returns {@link Observable} that will load some newer limited by maximum pages loading results.
*
* @param maxPageDeep Limit to load pages;
* @return Returns {@link Observable} to limited load newer items.
*/
@NonNull
public Observable<TLoadedItems> loadNewest(final int maxPageDeep) {
return loadingNewerObservable
@ -163,6 +199,11 @@ public class LoadingRenewableList<TItem, TReference, TNewerReference,
.last();
}
/**
* Returns {@link Observable} that tries to load some newer items even if there are no info about count of them.
*
* @return {@link Observable} to load newer items.
*/
@NonNull
public Observable<TLoadedItems> renew() {
return loadingNewestObservable;

View File

@ -23,8 +23,22 @@ import android.support.annotation.NonNull;
import rx.Observable;
/**
* Created by Gavriil Sitnikov on 02/06/2016.
* Object that is loading next part of items by reference or position.
*
* @param <TItem> Type of items to be loaded;
* @param <TMoreReference> Type of reference to be used to load next part of items;
* @param <TLoadedItems> Type of loaded items part.
*/
public interface MoreItemsLoader<TItem, TMoreReference, TLoadedItems extends LoadedItems<TItem, TMoreReference>> {
/**
* Returns {@link Observable} that could load next part of items.
*
* @param moreLoadRequest Request with info inside to load next part of items;
* @return {@link Observable} of loading items.
*/
@NonNull
Observable<TLoadedItems> load(@NonNull final MoreLoadRequest<TMoreReference> moreLoadRequest);

View File

@ -23,6 +23,12 @@ import android.support.annotation.Nullable;
import ru.touchin.roboswag.core.utils.ObjectUtils;
/**
* Created by Gavriil Sitnikov on 02/06/2016.
* Request represents request to load next part of items.
*
* @param <TMoreReference> Type of reference to load next part of items.
*/
public class MoreLoadRequest<TMoreReference> {
@Nullable
@ -34,11 +40,21 @@ public class MoreLoadRequest<TMoreReference> {
this.nextPosition = nextPosition;
}
/**
* Returns reference to be used to load next part of items.
*
* @return Reference object.
*/
@Nullable
public TMoreReference getReference() {
return moreReference;
}
/**
* Returns position of next item to load.
*
* @return Position of next item.
*/
public int getNextPosition() {
return nextPosition;
}

View File

@ -23,6 +23,14 @@ import android.support.annotation.NonNull;
import rx.Observable;
/**
* Created by Gavriil Sitnikov on 02/06/2016.
* Object that is loading new part of items by reference.
*
* @param <TItem> Type of items to be loaded;
* @param <TNewerReference> Type of reference to be used to load new part of items;
* @param <TLoadedItems> Type of loaded items part.
*/
public interface NewerItemsLoader<TItem, TReference, TNewerReference,
TLoadedItems extends LoadedRenewableItems<TItem, TReference, TNewerReference>> {

View File

@ -23,6 +23,12 @@ import android.support.annotation.Nullable;
import ru.touchin.roboswag.core.utils.ObjectUtils;
/**
* Created by Gavriil Sitnikov on 02/06/2016.
* Request represents request to load new part of items.
*
* @param <TNewerReference> Type of reference to load new part of items.
*/
public class NewerLoadRequest<TNewerReference> {
@Nullable
@ -34,11 +40,21 @@ public class NewerLoadRequest<TNewerReference> {
this.newerItemsCount = newerItemsCount;
}
/**
* Returns reference to be used to load new part of items.
*
* @return Reference object.
*/
@Nullable
public TNewerReference getNewerReference() {
return newerReference;
}
/**
* Count of newer items to load.
*
* @return Count of newer items to load.
*/
public int getNewerItemsCount() {
return newerItemsCount;
}

View File

@ -232,7 +232,7 @@ public class Storable<TKey, TObject, TStoreObject> {
/**
* Creates observable which is async setting value to store.
* It could emit only completed and errors events.
* NOTE: It could emit ONLY completed and errors events. It is not providing onNext event!
* Errors won't be emitted if {@link #getStore()} implements {@link SafeStore} and {@link #getConverter()} implements {@link SafeConverter}.
*
* @param newValue Value to set;