I have a Fragment in which I fetch some blogs as soon as it loads. I am doing pagination here, so, I load data for page=1 initially.
I also have a scrollListener implemented which makes subsequent API calls to load more blogs as user scroll downs. Every time a new call is made, I add a progressBar at the end of the recyclerview. The code is given below.
The issue that is happening is, I am getting multiple progressdialogs as shown in the image . Also, even the page number keeps increasing and it keeps on loading more data. Without adding line numbers (1-4), there is no issue of endless data coming. I just don't get progressdialog.
I just don't understand the issue with the code. I simply want to add progressdialog at the end of recyclerview whenever new API call is made.
BlogsRecyclerViewAdapter adapter;
ArrayList<BlogResponse> blogsList;
// Code for scrollListener in Fragment
blogsList = new ArrayList<>();
adapter = new BlogsRecyclerViewAdapter(getContext(), blogsList);
blogsRecyclerView.setAdapter(adapter);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
blogsRecyclerView.setLayoutManager(linearLayoutManager);
scrollListener = new BlogsRecyclerViewScrollListener(linearLayoutManager) {
@Override
public boolean onLoadMore(final int page, int totalItemsCount, RecyclerView view) {
blogsList.add(null); //line-1
adapter.notifyItemInserted(blogsList.size()-1); //line-2
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
// remove progress item
blogsList.remove(blogsList.size() - 1); //line-3
adapter.notifyItemRemoved(blogsList.size()); //line-4
fetchBlogs(page);
}
}, 2000); //time 2 seconds
return true; // ONLY if more data is actually being loaded; false otherwise.
}
};
fetchBlogs(1);
blogsRecyclerView.addOnScrollListener(scrollListener);
// BlogsRecyclerViewScrollListener
public abstract class BlogsRecyclerViewScrollListener extends RecyclerView.OnScrollListener{
private int visibleThreshold = 3;
private int currentPage = 1;
private int previousTotalItemCount = 0;
private boolean loading = true;
private int startingPageIndex = 1;
RecyclerView.LayoutManager mLayoutManager;
public BlogsRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
}
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
}
else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}
@Override
public void onScrolled(RecyclerView view, int dx, int dy) {
int lastVisibleItemPosition = 0;
int totalItemCount = mLayoutManager.getItemCount();
lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
}
}
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
if (!loading && (lastVisibleItemPosition + visibleThreshold) >= totalItemCount) {
currentPage++;
onLoadMore(currentPage, totalItemCount, view);
loading = true;
}
}
public void resetState() {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
}
public abstract boolean onLoadMore(int page, int totalItemsCount,
RecyclerView view);
}
// fetch Blogs method
private void fetchBlogs(final int page) {
apiServiceWithoutVersion.getBlogs(String.valueOf(page))
.enqueue(new
Callback<ArrayList<BlogResponse>>() {
@Override
public void onResponse(Call<ArrayList<BlogResponse>> call,
Response<ArrayList<BlogResponse>> response) {
if(response.isSuccessful()){
for(BlogResponse blogResponse: response.body()){
blogsList.add(blogResponse);
}
adapter.notifyDataSetChanged();
}else{
//some code to show error
}
}
@Override
public void onFailure(Call<ArrayList<BlogResponse>> call, Throwable t) {
//some code to show failure
}
});
}
// item_loading.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progress_bar_at_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
// BlogsRecyclerViewAdapter
public class BlogsRecyclerViewAdapter extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context mContext;
ArrayList<BlogResponse> mObjects;
ArrayList<BlogResponse> mFilteredObjects;
onItemClickListener mListener;
private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;
public void setOnItemClickListener(onItemClickListener listener){
mListener = listener;
}
public BlogsRecyclerViewAdapter(Context context, ArrayList<BlogResponse> objects){
mContext = context;
mObjects = objects;
mFilteredObjects = objects;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder holder = null;
if(viewType==VIEW_ITEM) {
View view = View.inflate(mContext, R.layout.list_item_blogs_recycler_view, null);
holder = new BlogViewHolder(view);
}else{
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_loading, parent, false);
holder = new ProgressViewHolder(v);
}
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(holder instanceof BlogViewHolder){
//code for blogs
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onItemClick(position);
}
});
}else{
((ProgressViewHolder)holder).progressBar.setIndeterminate(true);
}
}
@Override
public int getItemCount() {
return mFilteredObjects.size();
}
private class BlogViewHolder extends RecyclerView.ViewHolder {
public BlogViewHolder(View itemView) {
super(itemView);
// Code for blogs
}
}
private class ProgressViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public ProgressViewHolder(View v) {
super(v);
progressBar = v.findViewById(R.id.progress_bar_at_bottom);
}
}
public interface onItemClickListener{
void onItemClick(int position);
}
@Override
public int getItemViewType(int position) {
return mObjects.get(position)!=null? VIEW_ITEM: VIEW_PROG;
}
}