4

I created a RecyclerView for my application and trying to find a way to stop huge requests, I want to get the results 10 by 10 with a progress bar. My server will send the results 10 by 10 on every scrolldown to last item.

    public class ProfileActivityFriendsList extends AppCompatActivity {
        String[] names={"Ander Herera","David De Gea","Michael Carrick","Juan Mata","Diego Costa","Oscar"};
        String[] positions={"Midfielder","GoalKeeper", "Midfielder","Playmaker","Striker","Playmaker"};
        String[] urls={"Midfielder","GoalKeeper", "Midfielder","Playmaker","Striker","Playmaker"};
        int[] images = {R.mipmap.ic_launcher,R.mipmap.ic_launcher, R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher};

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_profile_friends_list);

            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

            //GET RECYCLER
            RecyclerView rv = (RecyclerView) findViewById(R.id.myRecycler);
            //SET LAYOUT
            rv.setLayoutManager(new LinearLayoutManager(this));
            rv.setItemAnimator(new DefaultItemAnimator());
            //ADAPTER
            MyAdapter adapter = new MyAdapter(this, names, positions, urls, images);
            rv.setAdapter(adapter);
        }
} 

Here is my adapter class.

public class MyAdapter extends RecyclerView.Adapter<MyHolder> {
    Context c;
    String[] names;
    String[] positions;
    String[] urls;
    int[] img;

    public MyAdapter(Context ctx, String[] names, String[] positions,String[] urls, int[] images){
        this.c=ctx;
        this.names = names;
        this.positions = positions;
        this.img = images;
        this.urls = urls;
    }
    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.friend_list_model,null);

        MyHolder holder = new MyHolder(v);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyHolder holder, final int position) {
        holder.imageView.setImageResource(img[position]);
        holder.name.setText(names[position]);
        holder.desc.setText(positions[position]);

        holder.serItemClickListener(new ItemClickListener() {
            @Override
            public void onItemClick(View v, int pos) {
                Snackbar.make(v,positions[position]+" "+positions[position],Snackbar.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return names.length;
    }
}

and this it the holder.

public class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    CircleImageView imageView;
    TextView name;
    TextView desc;
    ItemClickListener itemClickListener;
    public MyHolder(View itemView) {
        super(itemView);

        imageView = (CircleImageView) itemView.findViewById(R.id.circleImageView1);
        name = (TextView) itemView.findViewById(R.id.textName);
        desc = (TextView) itemView.findViewById(R.id.textDesc);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        this.itemClickListener.onItemClick(v,getLayoutPosition());
    }
    public void serItemClickListener(ItemClickListener ic){
        this.itemClickListener = ic;
    }
}

I watched lots of tutorials and couldn't find a clear solution, I think there are some ways to do it but I don't know is my code available to add it?

Ahmet Aziz Beşli
  • 1,096
  • 2
  • 13
  • 31

3 Answers3

5

What we did was use ReyclerView.OnScrollListener. Assuming you're using a LinearLayoutManager, you can check the current shown item versus the total count to determine when you've reached the last item, then request the next page. You also need to throw in some additional logic checks to early out to prevent "spamming" as the scroll even happens a lot.

For example:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        if (!hasMoreContent()) {
            return;
        }

        if (currentlyLoadingInitialRequest()) {
            return;
        }

        if (alreadyLoadingNextPage()) {
            return;
        }

        if (isInErrorState()) {
            return;
        }

        LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        int total = layoutManager.getItemCount();
        int currentLastItem = layoutManger.findLastVisibleItemPosition();
        if (currentLastItem == total - 1) {
            requestNextPage();
        }
    });
dominicoder
  • 7,166
  • 1
  • 18
  • 31
5

https://github.com/kunal-mahajan/PaginationAdeptor

I have implemented the pagination component / widget and that is very simple to implement. No xml is required only need to extend the class. Example is available in above url with timer task and dummy data. In main activity you may change the number of data available for testing purpose in "final int totalRecords"; If there is any issue will answer your queries. Thanks Kunal

aanshu
  • 1,572
  • 11
  • 13
  • Really nice sample its work for me many thanks kunal! I found it interesting solution to the complex problem. Its also working on if the request cout does not fill the screen, it automatically load new request. – krishan mohan verma Jul 10 '18 at 05:51
  • Amazing code Sir. You have simplified any list loading screen whether horizontal or vertical with auto pagination and only requirement is to create adapter class for any screen. Loved this code Sir. Thanks ! – Sourab Sharma Jul 10 '18 at 06:19
  • Thank you so much sir, saved more than a day of work. – sam2395 Jul 10 '18 at 06:22
2

You can try this approach:

  mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        if (dy > 0) //check for scroll down
        {
            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisibleItems = mLayoutManager.findFirstVisibleItemPosition();

            if (loading) {
                if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
                    loading = false;
                    if (adapter.countOfShowing < adapter.allChallenges.size()) {
                        Log.e("...", "Last Item Wow !");
                        adapter.increaseCountOfShowing();
                        adapter.notifyDataSetChanged();
                    }
                    loading = true;
                    //Do pagination.. i.e. fetch new data
                }
            }
        }
    }
});
Pavel Savchkov
  • 139
  • 1
  • 8
  • can you give some examples for adapter.countOfShowing, adapter.allChallenges.size(), adapter.increaseCountOfShowing()? how do i need to implement them? – Ahmet Aziz Beşli Aug 27 '17 at 20:53
  • Oh, yeah, sorry. I've simply copied my own code here. I keep 2 arrays in my adapter allItems and showedItems (let's call them so). increaseCountOfShowing() is just increasing the showedItemsSize and fill them with AllItems elements. Are you clear with that? – Pavel Savchkov Aug 27 '17 at 21:01
  • 1
    nop :D, I will try to find a way to understand the onScrolled and the adapter issues. thanks for your help!. – Ahmet Aziz Beşli Aug 27 '17 at 21:16
  • 1
    I did all the parts except the countOfShowing man. how did you get the countOfShowing as int? what is the method of it? – Ahmet Aziz Beşli Aug 27 '17 at 22:11
  • There is just a simple method which increases variable countOfShowing called increaseCountOfShowing() for example by 10. Then I reinit showedItems array with a new size and fill that with allItems elements – Pavel Savchkov Aug 28 '17 at 07:50