, , , , github , , , .
, . RecyclerView.Adapter
data adapter
(Map<Integer, DataItem>
).
TwoWayEndlessAdapter.java
public abstract class TwoWayEndlessAdapter<VH extends RecyclerView.ViewHolder, DataItem> extends RecyclerView.Adapter<VH> {
protected List<DataItem> data;
private Callback mEndlessCallback = null;
private int bottomAdvanceCallback = 0;
private boolean isFirstBind = true;
public void setEndlessCallback(Callback callback)
{
mEndlessCallback = callback;
}
public void addItemsAtBottom(ArrayList<DataItem> bottomList)
{
if (data == null) {
throw new NullPointerException("Data container is `null`. Are you missing a call to setDataContainer()?");
}
if (bottomList == null || bottomList.isEmpty()) {
return;
}
int adapterSize = getItemCount();
data.addAll(adapterSize, bottomList);
notifyItemRangeInserted(adapterSize, adapterSize + bottomList.size());
}
public void addItemsAtTop(ArrayList<DataItem> topList)
{
if (data == null) {
throw new NullPointerException("Data container is `null`. Are you missing a call to setDataContainer()?");
}
if (topList == null || topList.isEmpty()) {
return;
}
Collections.reverse(topList);
data.addAll(0, topList);
notifyItemRangeInserted(0, topList.size());
}
public void setBottomAdvanceCallback(int bottomAdvance)
{
if (bottomAdvance < 0) {
throw new IndexOutOfBoundsException("Invalid index, bottom index must be greater than 0");
}
bottomAdvanceCallback = bottomAdvance;
}
public void setDataContainer(List<DataItem> data)
{
this.data = data;
}
@Override
public void onBindViewHolder(VH holder, int position)
{
EndlessLogger.logD("onBindViewHolder() for position : " + position);
onBindViewHolder(holder, data.get(position), position);
if (position == 0 && !isFirstBind) {
notifyTopReached();
}
else if ((position + bottomAdvanceCallback) >= (getItemCount() - 1)) {
notifyBottomReached();
}
isFirstBind = false;
}
public abstract void onBindViewHolder(VH holder, DataItem data, int position);
protected void notifyTopReached()
{
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (mEndlessCallback != null) {
mEndlessCallback.onTopReached();
}
}
}, 50);
}
protected void notifyBottomReached()
{
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (mEndlessCallback != null) {
mEndlessCallback.onBottomReached();
}
}
}, 50);
}
public interface Callback {
void onTopReached();
void onBottomReached();
}
}
.
TwoWayEndlessAdapterImp.java
public class TwoWayEndlessAdapterImp<VH extends RecyclerView.ViewHolder> extends TwoWayEndlessAdapter<VH, ValueItem> {
@Override
public int getItemViewType(int position)
{
return R.layout.item_layout;
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType)
{
View itemViewLayout = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
switch (viewType)
{
case R.layout.item_layout:
return (VH) new ItemLayoutViewHolder(itemViewLayout);
default:
return null;
}
}
@Override
public void onBindViewHolder(VH holder, ValueItem item, int position)
{
switch (getItemViewType(position)) {
case R.layout.item_layout:
ItemLayoutViewHolder viewHolder = (ItemLayoutViewHolder) holder;
viewHolder.textView.setText(item.data);
break;
}
}
@Override
public int getItemCount()
{
return data == null ? 0 : data.size();
}
}
TwoWayEndlessAdapter
TwoWayEndlessAdapterImp endlessAdapter = new TwoWayEndlessAdapterImp<>();
endlessAdapter.setDataContainer(new ArrayList<DataItem>());
endlessAdapter.setEndlessCallback(this);
, addItemsAtBottom(list);
, addItemsAtTop(list);
.