Skip to content

Instantly share code, notes, and snippets.

@shayousefi
Last active September 13, 2015 00:48
Show Gist options
  • Save shayousefi/e2952ab636f6ce593ff2 to your computer and use it in GitHub Desktop.
Save shayousefi/e2952ab636f6ce593ff2 to your computer and use it in GitHub Desktop.
A RecyclerView adapter backed by a list.
/*
* Copyright 2015 Shahin Yousefi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* An {@code RecyclerView.Adapter} backed by a {@link List}.
*
* @param <VH> type of {@code RecyclerView.ViewHolder}
* @param <E> type of list element
*/
public abstract class ListRecyclerAdapter<VH extends RecyclerView.ViewHolder, E>
extends RecyclerView.Adapter<VH> {
protected List<E> list;
public ListRecyclerAdapter() {
list = Collections.synchronizedList(new LinkedList<E>());
}
public ListRecyclerAdapter(@NonNull Collection<? extends E> items) {
list = Collections.synchronizedList(new LinkedList<>(items));
}
@Override
public int getItemCount() {
return list.size();
}
/**
* Adds the specified item at the end of the underlying list,
* and notifies any registered observers.
*
* @param item the item to add
*/
public void addItem(E item) {
addItem(list.size(), item);
}
/**
* Inserts the specified item into the underlying list at the specified location,
* and notifies any registered observers.
*
* @param position the index at which to insert
* @param item the item to add
*/
public void addItem(int position, E item) {
list.add(position, item);
notifyItemInserted(position);
}
/**
* Adds the items in the specified collection to the end of the underlying list,
* and notifies any registered observers.
*
* @param items the collection of items
*/
public void addAllItems(@NonNull Collection<? extends E> items) {
addAllItems(list.size(), items);
}
/**
* Inserts the items in the specified collection at the specified location in
* the underlying list, and notifies any registered observers.
*
* @param startPosition the index at which to start inserting items
* @param items the collection of items to be inserted
*/
public void addAllItems(int startPosition, @NonNull Collection<? extends E> items) {
if (list.addAll(startPosition, items)) {
notifyItemRangeInserted(startPosition, items.size());
}
}
/**
* Removes all elements from the underlying list, leaving it empty,
* and notifies any registered observers.
*/
public void clearItems() {
int itemCount = list.size();
list.clear();
notifyItemRangeRemoved(0, itemCount);
}
/**
* Tests whether the underlying list contains the specified item.
*
* @param item the item to search for
* @return {@code true} if item is an element of the underlying list, {@code false} otherwise.
*/
public boolean containsItem(E item) {
return list.contains(item);
}
/**
* Tests whether the underlying list contains all items contained in the specified collection.
*
* @param items the collection of items
* @return {@code true} if all items in the specified collection are elements of
* the underlying list, {@code false} otherwise.
*/
public boolean containsAllItems(@NonNull Collection<? extends E> items) {
return list.containsAll(items);
}
/**
* Returns the element at the specified location in the underlying list.
*
* @param position the index of the element to return
* @return The element at the specified location.
*/
public E getItem(int position) {
return list.get(position);
}
/**
* Returns an unmodifiable list of the specified portion of the underlying list.
*
* @param startPosition the index at which to start the sublist
* @param itemCount the number of items to include in the sublist
* @return An unmodifiable sublist of the underlying list.
*/
public List<E> getItems(int startPosition, int itemCount) {
return Collections.unmodifiableList(list.subList(startPosition, startPosition + itemCount));
}
/** Returns an unmodifiable list of all items in this adapter. */
public List<E> getListItems() {
return Collections.unmodifiableList(list);
}
/**
* Searches the underlying list for the specified item and returns the index of
* the first occurrence.
*
* @param item the item to search for
* @return The index of the first occurrence of the item or -1 if the item was not found.
*/
public int indexOf(E item) {
return list.indexOf(item);
}
/**
* Returns whether the underlying list contains no elements.
*
* @return {@code true} if the underlying list has no elements, {@code false} otherwise.
*/
public boolean isEmpty() {
return list.isEmpty();
}
/**
* Searches the underlying list for the specified item and returns the index of
* the last occurrence.
*
* @param item the item to search for
* @return The index of the last occurrence of the item, or -1 if the item was not found.
*/
public int lastIndexOf(E item) {
return list.lastIndexOf(item);
}
/**
* Moves the item at {@code fromPosition} to {@code toPosition} in the underlying list.
*
* @param fromPosition previous position of the item
* @param toPosition new position of the item
*/
public void moveItem(int fromPosition, int toPosition) {
if (fromPosition != toPosition) {
list.add(toPosition, list.remove(fromPosition));
notifyItemMoved(fromPosition, toPosition);
}
}
/**
* Removes the item at the specified location from the underlying list,
* and notifies any registered observers.
*
* @param position the index of the item to remove
* @return The removed item.
*/
public E removeItem(int position) {
E item = list.remove(position);
notifyItemRemoved(position);
return item;
}
/**
* Removes the first occurrence of the specified item from the underlying list,
* and notifies any registered observers.
*
* @param item the item to remove
*/
public void removeItem(E item) {
int position = list.indexOf(item);
if (position >= 0 && list.remove(item)) {
notifyItemRemoved(position);
}
}
/**
* Removes the specified portion of the underlying list.
*
* @param startPosition the index at which to start removing items
* @param itemCount the number of items to remove
*/
public void removeItems(int startPosition, int itemCount) {
list.subList(startPosition, startPosition + itemCount).clear();
notifyItemRangeRemoved(startPosition, itemCount);
}
/**
* Removes all occurrences in the underlying list of each item in the specified collection,
* and notifies any registered observers.
*
* @param items the collection of items to remove
*/
public void removeAllItems(@NonNull Collection<? extends E> items) {
if (list.removeAll(items)) {
notifyDataSetChanged();
}
}
/**
* Removes all items from the underlying list that are not contained in
* the specified collection, and notifies any registered observers.
*
* @param items the collection of items to retain
*/
public void retainAllItems(@NonNull Collection<? extends E> items) {
if (list.retainAll(items)) {
notifyDataSetChanged();
}
}
/**
* Replaces the element at the specified location in the underlying list with
* the specified item, and notifies any registered observers.
*
* @param position the index at which to put the specified item
* @param item the item to insert
* @return The previous element at the index.
*/
public E setItem(int position, E item) {
E oldItem = list.set(position, item);
notifyItemChanged(position);
return oldItem;
}
/**
* Replaces the items at the specified portion of the underlying list with items
* from the given collection, and notifies any registered observers.
*
* @param startPosition the index at which to start replacing items
* @param items the collection of items to replace existing items with
* @return An unmodifiable list of the replaced items.
*/
public List<E> setAllItems(int startPosition, @NonNull Collection<? extends E> items) {
int itemCount = items.size();
List<E> oldItems = new ArrayList<>(itemCount);
List<E> sublist = list.subList(startPosition, startPosition + itemCount);
int i = 0;
for (E item : items) {
oldItems.add(sublist.set(i, item));
i++;
}
notifyItemRangeChanged(startPosition, itemCount);
return Collections.unmodifiableList(oldItems);
}
/**
* Repopulates the underlying list with items from the specified collection,
* and notifies any registered observers.
*
* @param items the collection of items to insert to a fresh list
*/
public void setListItems(@NonNull Collection<? extends E> items) {
int itemCount = list.size();
list.clear();
if (list.addAll(items)) {
notifyDataSetChanged();
} else {
notifyItemRangeRemoved(0, itemCount);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment