package party.danyang.nationalgeographic.adapter.base;
import android.annotation.TargetApi;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
/**
* Created by Mr_Wrong on 15/10/10.
*/
public abstract class ArrayRecyclerAdapter<E, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> implements List<E> {
private final Object lock = new Object();
private final List<E> list;
@SuppressWarnings("unused")
public ArrayRecyclerAdapter() {
list = new ArrayList<>();
}
@SuppressWarnings("unused")
public ArrayRecyclerAdapter(int capacity) {
list = new ArrayList<>(capacity);
}
@SuppressWarnings("unused")
public ArrayRecyclerAdapter(Collection<? extends E> collection) {
list = (collection == null ? new ArrayList<E>() : new ArrayList<E>(collection));
}
@Override
public int getItemCount() {
return size();
}
@Override
public void add(int location, E object) {
synchronized (lock) {
list.add(location, object);
notifyItemInserted(location);
}
}
@Override
public boolean add(E object) {
synchronized (lock) {
int lastIndex = list.size();
if (list.add(object)) {
notifyItemInserted(lastIndex);
return true;
} else {
return false;
}
}
}
@Override
public boolean addAll(int location, @NonNull Collection<? extends E> collection) {
synchronized (lock) {
if (list.addAll(location, collection)) {
notifyItemRangeInserted(location, collection.size());
return true;
} else {
return false;
}
}
}
@Override
public boolean addAll(@NonNull Collection<? extends E> collection) {
synchronized (lock) {
int lastIndex = list.size();
if (list.addAll(collection)) {
notifyItemRangeInserted(lastIndex, collection.size());
return true;
} else {
return false;
}
}
}
@Override
public void clear() {
synchronized (lock) {
int size = list.size();
if (size > 0) {
list.clear();
notifyItemRangeRemoved(0, size);
}
}
}
@Override
public boolean contains(Object object) {
return list.contains(object);
}
@Override
public boolean containsAll(@NonNull Collection<?> collection) {
return list.containsAll(collection);
}
@Override
public E get(int location) {
return list.get(location);
}
@Override
public int indexOf(Object object) {
return list.indexOf(object);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@NonNull
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public int lastIndexOf(Object object) {
return list.lastIndexOf(object);
}
@NonNull
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@NonNull
@Override
public ListIterator<E> listIterator(int location) {
return list.listIterator(location);
}
@Override
public E remove(int location) {
synchronized (lock) {
E item = list.remove(location);
notifyItemRemoved(location);
return item;
}
}
@Override
public boolean remove(Object object) {
synchronized (lock) {
int index = indexOf(object);
if (list.remove(object)) {
notifyItemRemoved(index);
return true;
} else {
return false;
}
}
}
@Override
public boolean removeAll(@NonNull Collection<?> collection) {
boolean modified = false;
Iterator<E> iterator = list.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
if (collection.contains(object)) {
synchronized (lock) {
int index = indexOf(object);
iterator.remove();
notifyItemRemoved(index);
}
modified = true;
}
}
return modified;
}
@Override
public boolean retainAll(@NonNull Collection<?> collection) {
boolean modified = false;
Iterator<E> iterator = list.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
if (!collection.contains(object)) {
synchronized (lock) {
int index = indexOf(object);
iterator.remove();
notifyItemRemoved(index);
}
modified = true;
}
}
return modified;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public E set(int location, E object) {
synchronized (lock) {
E origin = list.set(location, object);
if (!Objects.equals(object, origin)) {
notifyItemChanged(location);
}
return origin;
}
}
@Override
public int size() {
return list.size();
}
@NonNull
@Override
public List<E> subList(int start, int end) {
return list.subList(start, end);
}
@NonNull
@Override
public Object[] toArray() {
return list.toArray();
}
@NonNull
@Override
@SuppressWarnings("SuspiciousToArrayCall")
public <T> T[] toArray(@NonNull T[] array) {
return list.toArray(array);
}
public void replaceWith(List<E> data) {
if (list.isEmpty() && data.isEmpty()) {
return;
}
if (list.isEmpty()) {
addAll(data);
return;
}
if (data.isEmpty()) {
clear();
return;
}
if (list.equals(data)) {
return;
}
// 首先将旧列表有、新列表没有的从旧列表去除
retainAll(data);
// 如果列表被完全清空了,那就直接全部插入好了
if (list.isEmpty()) {
addAll(data);
return;
}
// 然后遍历新列表,对旧列表的数据更新、移动、增加
for (int indexNew = 0; indexNew < data.size(); indexNew++) {
E item = data.get(indexNew);
int indexOld = indexOf(item);
if (indexOld == -1) {
add(indexNew, item);
} else if (indexOld == indexNew) {
set(indexNew, item);
} else {
list.remove(indexOld);
list.add(indexNew, item);
notifyItemMoved(indexOld, indexNew);
}
}
}
public void setNewData(@NonNull Collection<? extends E> collection) {
synchronized (lock) {
clear();
addAll(collection);
}
}
public List<E> getList() {
return list;
}
}