package com.jdroid.android.recycler; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import com.jdroid.android.R; import com.jdroid.android.application.AbstractApplication; import com.jdroid.android.fragment.FragmentHelper; import com.jdroid.android.usecase.PaginatedUseCase; import com.jdroid.java.exception.AbstractException; import java.util.List; public abstract class AbstractPaginatedRecyclerFragment extends AbstractRecyclerFragment { protected PaginatedUseCase<Object> paginatedUseCase; private int loadingItemViewType; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); paginatedUseCase = createPaginatedUseCase(); } @Override public void onStart() { super.onStart(); registerUseCase(paginatedUseCase, this, getUseCaseTrigger()); } protected FragmentHelper.UseCaseTrigger getUseCaseTrigger() { return FragmentHelper.UseCaseTrigger.ONCE; } @Override public void onStop() { super.onStop(); unregisterUseCase(paginatedUseCase, this); } protected abstract PaginatedUseCase<Object> createPaginatedUseCase(); protected abstract RecyclerViewAdapter createAdapter(List<Object> items); private void setAdapter() { RecyclerViewAdapter adapter = createAdapter(paginatedUseCase.getResults()); loadingItemViewType = adapter.addRecyclerViewType(new LoadingRecyclerViewType()); setAdapter(adapter); } @Override public void onStartUseCase() { if (paginatedUseCase.isPaginating()) { executeOnUIThread(new Runnable() { @Override public void run() { // Add loading footer int lastPosition = getAdapter().getItemCount() - 1; if (lastPosition >= 0) { int itemViewType = getAdapter().getItemViewType(getAdapter().getItemCount() - 1); if (itemViewType != loadingItemViewType) { getAdapter().addItem(new Object()); } } } }); } else { super.onStartUseCase(); } } @Override public void onFinishFailedUseCase(AbstractException abstractException) { if (paginatedUseCase.isPaginating()) { AbstractApplication.get().getExceptionHandler().logHandledException(abstractException); executeOnUIThread(new Runnable() { @Override public void run() { dismissPaginationLoading(); } }); } else { super.onFinishFailedUseCase(abstractException); } } private void dismissPaginationLoading() { int lastPosition = getAdapter().getItemCount() - 1; if (lastPosition >= 0) { int itemViewType = getAdapter().getItemViewType(getAdapter().getItemCount() - 1); if (itemViewType == loadingItemViewType) { getAdapter().removeItemByPosition(lastPosition); } } } @Override public void onFinishUseCase() { executeOnUIThread(new Runnable() { @SuppressWarnings("unchecked") @Override public void run() { if (paginatedUseCase.isPaginating()) { dismissPaginationLoading(); getAdapter().addItems(paginatedUseCase.getResults()); dismissLoading(); } else { if ((getItemsToAutoPaginate() != null) && (paginatedUseCase.getResults().size() <= getItemsToAutoPaginate())) { if (paginatedUseCase.getResults().isEmpty()) { setAdapter(); } else { setAdapter(); dismissLoading(); } paginatedUseCase.markAsPaginating(); executeUseCase(paginatedUseCase); } else { setAdapter(); dismissLoading(); } } } }); } @Override public void setAdapter(RecyclerViewAdapter adapter) { super.setAdapter(adapter); RecyclerView recyclerView = getRecyclerView(); if (recyclerView != null) { recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (!paginatedUseCase.isInProgress() && !paginatedUseCase.isLastPage()) { int visibleItemCount = getLayoutManager().getChildCount(); int totalItemCount = getLayoutManager().getItemCount(); int firstVisibleItemPosition = ((LinearLayoutManager)getLayoutManager()).findFirstVisibleItemPosition(); if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount - 4 && firstVisibleItemPosition >= 0) { paginatedUseCase.markAsPaginating(); executeUseCase(paginatedUseCase); } } } }); } } protected Integer getItemsToAutoPaginate() { return null; } protected int getPaginationFooterResId() { return R.layout.jdroid_pagination_footer; } public class LoadingRecyclerViewType extends SimpleRecyclerViewType { @Override protected Integer getLayoutResourceId() { return AbstractPaginatedRecyclerFragment.this.getPaginationFooterResId(); } @Override public AbstractRecyclerFragment getAbstractRecyclerFragment() { return AbstractPaginatedRecyclerFragment.this; } @Override protected Boolean isClickable() { return false; } } }