涂鸦礼物初版实现
This commit is contained in:
@@ -2,7 +2,9 @@ package com.yizhuan.xchat_android_library.bindinglist;
|
||||
|
||||
import androidx.databinding.ObservableArrayList;
|
||||
import androidx.databinding.ObservableList;
|
||||
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
@@ -16,47 +18,31 @@ import java.util.List;
|
||||
* Created by lvzebiao on 2018/10/23.
|
||||
*/
|
||||
|
||||
public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
public class MultiTypeAdapter<T extends IItem> extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
private List<IItem> headersItems = new ArrayList<>();
|
||||
|
||||
public List<IItem> getHeadersItems() {
|
||||
return headersItems;
|
||||
}
|
||||
|
||||
private ObservableList<IItem> footersItems = new ObservableArrayList<>();
|
||||
private final WeakReferenceOnListChangedCallback<T> callback = new WeakReferenceOnListChangedCallback<>(this);
|
||||
private List<T> headersItems = new ArrayList<>();
|
||||
private ObservableList<T> footersItems = new ObservableArrayList<>();
|
||||
/**
|
||||
* 此数据源表示真正的数据, 保留用于其他逻辑计算
|
||||
*/
|
||||
private List<IItem> dataItems;
|
||||
|
||||
public List<IItem> getData() {
|
||||
return dataItems;
|
||||
}
|
||||
|
||||
private List<T> dataItems;
|
||||
/**
|
||||
* 此list表示RecyclerView显示的所有item,即header+data+footer
|
||||
*/
|
||||
private ObservableList<IItem> allItems = new ObservableArrayList<>();
|
||||
|
||||
public List<IItem> getAllItems() {
|
||||
return allItems;
|
||||
}
|
||||
|
||||
private ObservableList<T> allItems = new ObservableArrayList<>();
|
||||
private boolean canLoadMore = false;
|
||||
|
||||
public void setCanLoadMore(boolean canLoadMore) {
|
||||
this.canLoadMore = canLoadMore;
|
||||
}
|
||||
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
private final WeakReferenceOnListChangedCallback callback = new WeakReferenceOnListChangedCallback(this);
|
||||
|
||||
private int variableId;
|
||||
private boolean needItemClick;
|
||||
private T loadMoreItem;
|
||||
private List<T> statusList = new ArrayList<>();
|
||||
private T startLoadingItem;
|
||||
private T netErrorItem;
|
||||
private T emptyItem;
|
||||
private OnItemClickListener<T> listener;
|
||||
|
||||
public MultiTypeAdapter(List<IItem> list, int variableId, boolean needItemClick) {
|
||||
public MultiTypeAdapter(List<T> list, int variableId, boolean needItemClick) {
|
||||
if (list == null) {
|
||||
list = new ObservableArrayList<>();
|
||||
}
|
||||
@@ -74,6 +60,28 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
this(null, variableId, false);
|
||||
}
|
||||
|
||||
static void ensureChangeOnMainThread() {
|
||||
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
|
||||
throw new IllegalStateException("You must only modify the ObservableList on the main thread.");
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> getHeadersItems() {
|
||||
return headersItems;
|
||||
}
|
||||
|
||||
public List<T> getData() {
|
||||
return dataItems;
|
||||
}
|
||||
|
||||
public List<T> getAllItems() {
|
||||
return allItems;
|
||||
}
|
||||
|
||||
public void setCanLoadMore(boolean canLoadMore) {
|
||||
this.canLoadMore = canLoadMore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 这方法不会清除header,清除header调用
|
||||
* {@link #clearAllItem()}
|
||||
@@ -87,7 +95,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
if (headersItems.size() == 0) {
|
||||
allItems.clear();
|
||||
} else {
|
||||
// List<IItem> tempList = new ArrayList<>();
|
||||
// List<T> tempList = new ArrayList<>();
|
||||
// for (int i = headersItems.size(); i < allItems.size(); i++) {
|
||||
// tempList.add(allItems.get(i));
|
||||
// }
|
||||
@@ -110,7 +118,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
allItems.clear();
|
||||
}
|
||||
|
||||
public void addData(List<IItem> list) {
|
||||
public void addData(List<T> list) {
|
||||
dataItems.addAll(list);
|
||||
int insertPos = allItems.size() - footersItems.size();
|
||||
if (insertPos < 0) {
|
||||
@@ -119,14 +127,12 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
allItems.addAll(insertPos, list);
|
||||
}
|
||||
|
||||
public void addHeaderItem(IItem headerItem) {
|
||||
public void addHeaderItem(T headerItem) {
|
||||
headersItems.add(headerItem);
|
||||
allItems.add(0, headerItem);
|
||||
}
|
||||
|
||||
private IItem loadMoreItem;
|
||||
|
||||
public void setLoadMoreView(IItem item) {
|
||||
public void setLoadMoreView(T item) {
|
||||
if (!canLoadMore || item == null) {
|
||||
return;
|
||||
}
|
||||
@@ -151,14 +157,11 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
}
|
||||
}
|
||||
|
||||
private List<IItem> statusList = new ArrayList<>();
|
||||
private IItem startLoadingItem;
|
||||
|
||||
/**
|
||||
* 此方法并不是所有list都需要,不需要则传null
|
||||
* 只是客户端有个加载动画,所以添加
|
||||
*/
|
||||
public void startLoading(IItem item) {
|
||||
public void startLoading(T item) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
@@ -171,12 +174,10 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
}
|
||||
}
|
||||
|
||||
private IItem netErrorItem;
|
||||
|
||||
/**
|
||||
* 如果有数据不添加错误item
|
||||
*/
|
||||
public void setNetError(IItem item) {
|
||||
public void setNetError(T item) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
@@ -195,9 +196,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
}
|
||||
}
|
||||
|
||||
private IItem emptyItem;
|
||||
|
||||
public void setEmpty(IItem item) {
|
||||
public void setEmpty(T item) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
@@ -221,24 +220,22 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
public void hideStatus() {
|
||||
statusList.clear();
|
||||
if (startLoadingItem != null && allItems.contains(startLoadingItem)) {
|
||||
if (startLoadingItem != null) {
|
||||
allItems.remove(startLoadingItem);
|
||||
}
|
||||
|
||||
if (netErrorItem != null && allItems.contains(netErrorItem)) {
|
||||
if (netErrorItem != null) {
|
||||
allItems.remove(netErrorItem);
|
||||
}
|
||||
if (emptyItem != null && allItems.contains(emptyItem)) {
|
||||
if (emptyItem != null) {
|
||||
allItems.remove(emptyItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearLoarMoreView() {
|
||||
footersItems.clear();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return allItems.get(position).getType();
|
||||
@@ -252,7 +249,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) {
|
||||
final IItem item = getIndexItem(position);
|
||||
final T item = getIndexItem(position);
|
||||
holder.bindTo(variableId, item);
|
||||
if (needItemClick) {
|
||||
holder.binding.getRoot().setOnClickListener(v -> {
|
||||
@@ -268,7 +265,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
return allItems.size();
|
||||
}
|
||||
|
||||
public IItem getIndexItem(int position) {
|
||||
public T getIndexItem(int position) {
|
||||
return allItems.get(position);
|
||||
}
|
||||
|
||||
@@ -280,16 +277,10 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
this.recyclerView = recyclerView;
|
||||
}
|
||||
|
||||
private OnItemClickListener listener;
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener listener) {
|
||||
public void setOnItemClickListener(OnItemClickListener<T> listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onClick(IItem item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
if (this.recyclerView != null && allItems != null) {
|
||||
@@ -298,16 +289,20 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
this.recyclerView = null;
|
||||
}
|
||||
|
||||
private static class WeakReferenceOnListChangedCallback extends ObservableList.OnListChangedCallback<ObservableList<IItem>> {
|
||||
final WeakReference<MultiTypeAdapter> adapterRef;
|
||||
public interface OnItemClickListener<T extends IItem> {
|
||||
void onClick(T item);
|
||||
}
|
||||
|
||||
WeakReferenceOnListChangedCallback(MultiTypeAdapter adapter) {
|
||||
private static class WeakReferenceOnListChangedCallback<T extends IItem> extends ObservableList.OnListChangedCallback<ObservableList<T>> {
|
||||
final WeakReference<MultiTypeAdapter<T>> adapterRef;
|
||||
|
||||
WeakReferenceOnListChangedCallback(MultiTypeAdapter<T> adapter) {
|
||||
this.adapterRef = new WeakReference<>(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(ObservableList sender) {
|
||||
MultiTypeAdapter adapter = adapterRef.get();
|
||||
MultiTypeAdapter<T> adapter = adapterRef.get();
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
@@ -317,7 +312,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
@Override
|
||||
public void onItemRangeChanged(ObservableList sender, final int positionStart, final int itemCount) {
|
||||
MultiTypeAdapter adapter = adapterRef.get();
|
||||
MultiTypeAdapter<T> adapter = adapterRef.get();
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
@@ -327,7 +322,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
@Override
|
||||
public void onItemRangeInserted(ObservableList sender, final int positionStart, final int itemCount) {
|
||||
MultiTypeAdapter adapter = adapterRef.get();
|
||||
MultiTypeAdapter<T> adapter = adapterRef.get();
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
@@ -337,7 +332,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
@Override
|
||||
public void onItemRangeMoved(ObservableList sender, final int fromPosition, final int toPosition, final int itemCount) {
|
||||
MultiTypeAdapter adapter = adapterRef.get();
|
||||
MultiTypeAdapter<T> adapter = adapterRef.get();
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
@@ -349,7 +344,7 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
|
||||
@Override
|
||||
public void onItemRangeRemoved(ObservableList sender, final int positionStart, final int itemCount) {
|
||||
MultiTypeAdapter adapter = adapterRef.get();
|
||||
MultiTypeAdapter<T> adapter = adapterRef.get();
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
@@ -357,10 +352,4 @@ public class MultiTypeAdapter extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
adapter.notifyItemRangeRemoved(positionStart, itemCount);
|
||||
}
|
||||
}
|
||||
|
||||
static void ensureChangeOnMainThread() {
|
||||
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
|
||||
throw new IllegalStateException("You must only modify the ObservableList on the main thread.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user