(Tutorial Android) Implement Pagination in RecyclerView

Saturday, April 09, 2016

Pagination merupakan suatu metode yang digunakan untuk membatasi data yang ditampilkan. Dengan menerapkan pagination, maka jumlah data yang ditampilkan per halamannya dibatasi, sehingga tidak perlu langsung mengambil semua data. Pada tutorial kali ini saya akan membahas cara menerapkan pagination di RecyclerView. Untuk itu saya anjurkan untuk melihat postingan saya tentang (Tutorial Android) RecyclerView and CardView Android Material Design

Oke kita akan menggunakan project dari postingan sebelumnya, hanya kita akan modifikasi sedikit.

Pertama, buat layout untuk menampilkan progressbar. Progressbar akan muncul dibagian bawah list ketika di scroll.

footer_loading.xml


Selanjutnya kita akan menambahkan progressbar tadi sebagai footer di RecyclerView. Modifikasi kelas MemberListAdapter.java berikut.

package wim.example.com.androidpaging.adapter;

package wim.example.com.androidpaging.adapter;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import wim.example.com.androidpaging.R;
import wim.example.com.androidpaging.model.Member;

/**
 * Created by wim on 4/6/16.
 */
public class MemberListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final int VIEW_TYPE_ITEM = 0;
    private final int VIEW_TYPE_LOADING = 1;

    private boolean loading = true;

    private List<Member> memberList;
    private OnItemClickListener onItemClickListener;

    public MemberListAdapter() {
        memberList = new ArrayList<>();
    }

    private void add(Member item) {
        memberList.add(item);
        notifyItemInserted(memberList.size());
    }

    public void addAll(List<Member> memberList) {
        for (Member member : memberList) {
            add(member);
        }
    }

    public void remove(Member item) {
        int position = memberList.indexOf(item);
        if (position > -1) {
            memberList.remove(position);
            notifyItemRemoved(position);
        }
    }

    public void clear() {
        while (getItemCount() > 0) {
            remove(getItem(0));
        }
    }

    public Member getItem(int position){
        return memberList.get(position);
    }

    @Override
    public int getItemViewType (int position) {
        if(isPositionFooter (position)) {
            return VIEW_TYPE_LOADING;
        }
        return VIEW_TYPE_ITEM;
    }

    private boolean isPositionFooter (int position) {
        return position == memberList.size();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_ITEM) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_member, parent, false);
            return new MemberViewHolder(view, onItemClickListener);
        } else if (viewType == VIEW_TYPE_LOADING) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_loading, parent, false);
            return new LoadingViewHolder(view);
        }

        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof MemberViewHolder) {
            MemberViewHolder memberViewHolder = (MemberViewHolder) holder;

            final Member member = memberList.get(position);

            memberViewHolder.memberThumb.setImageResource(member.getThumb());
            memberViewHolder.memberName.setText(member.getName());
            memberViewHolder.memberTeam.setText(member.getTeam());

        } else if (holder instanceof LoadingViewHolder) {
            LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
            loadingViewHolder.progressBar.setIndeterminate(true);
            loadingViewHolder.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
        }

    }

    public void setLoading(boolean loading){
        this.loading = loading;
    }

    @Override
    public int getItemCount() {
        return memberList == null ? 0 : memberList.size() + 1;
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    static class MemberViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        ImageView memberThumb;
        TextView memberName;
        TextView memberTeam;

        OnItemClickListener onItemClickListener;

        public MemberViewHolder(View itemView, OnItemClickListener onItemClickListener) {
            super(itemView);

            memberThumb = (ImageView) itemView.findViewById(R.id.thumb);
            memberName = (TextView) itemView.findViewById(R.id.name);
            memberTeam = (TextView) itemView.findViewById(R.id.team);

            itemView.setOnClickListener(this);
            this.onItemClickListener = onItemClickListener;
        }

        @Override
        public void onClick(View v) {
            onItemClickListener.onItemClick(v, getAdapterPosition());
        }
    }

    static class LoadingViewHolder extends RecyclerView.ViewHolder {
        public ProgressBar progressBar;

        public LoadingViewHolder(View itemView) {
            super(itemView);

            progressBar = (ProgressBar) itemView.findViewById(R.id.loading);
        }
    }


    public interface OnItemClickListener {

        void onItemClick(View view, int position);
    }
}


Lalu kita akan mengimplementasikan pagination dengan RecyclerView.OnScrollListener pada RecyclerView.
private RecyclerView.OnScrollListener recyclerViewOnScrollListener = new RecyclerView.OnScrollListener() {

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int visibleItemCount = linearLayoutManager.getChildCount();
        int totalItemCount = linearLayoutManager.getItemCount();
        int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
        if (!isLoading && !isLastPage) {
            if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
                    && firstVisibleItemPosition >= 0
                    && totalItemCount >= PAGE_SIZE) {
   isLoading = true;
   // load more data here

            }
        }
    }
};

Lalu modifikasi kelas MemberFragment.java berikut.
package wim.example.com.androidpaging.fragments;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import wim.example.com.androidpaging.R;
import wim.example.com.androidpaging.adapter.MemberListAdapter;
import wim.example.com.androidpaging.model.Member;

/**
 * Created by wim on 4/5/16.
 */
public class MemberFragment extends Fragment {

    private int PAGE_SIZE = 6;

    private boolean isLastPage = false;
    private boolean isLoading = false;

    private RecyclerView listMember;
    private LinearLayoutManager linearLayoutManager;
    private MemberListAdapter memberListAdapter;

    protected Context context;

    int thumb[] = {R.drawable.acha, R.drawable.yupi, R.drawable.della,
            R.drawable.kinal, R.drawable.uty, R.drawable.shafa,
            R.drawable.hanna, R.drawable.lidya, R.drawable.nadila,
            R.drawable.nat, R.drawable.sisil, R.drawable.viny,
            R.drawable.chika_chan, R.drawable.ikha, R.drawable.ayen,
            R.drawable.saktia, R.drawable.dudut, R.drawable.yona};

    String name[] = {"Alicia Chanzia", "Cindy Yuvia", "Della Delila", "Devi Kinal Putri",
            "Dwi Putri Bonita", "Fakhriyani Shafariyanti", "Jennifer Hanna", "Lidya Maulida Djuhandar",
            "Nadila Cindi Wantari", "Natalia", "Priscillia Sari Dewi", "Ratu Vienny Fitrilya",
            "Rina Chikano", "Riskha Fairunissa", "Rona Anggreani", "Saktia Oktapyani",
            "Sinka Juliani", "Viviyona Apriani"};

    String motto[] = {"Hap!Tangkap Aku!", "Mau Kemana Kita?", "Future Processor", "K3bahagiaan Depi",
            "Different", "Shafa Disana?", "Target", "Banyak Mau", "Yossha Ikuzo!", "Spicy Hot",
            "Yuk Isi Batre Senter", "#KitaBisa", "Yuk.. Kita Dangdutan!", "Nothing Gonna Stop Us Now",
            "Stand Up!", "Saktia Dalam Jiwa", "Berarti Dalam Hidup", "Life In Technicolor"};

    public static MemberFragment newInstance(){
        return new MemberFragment();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_member, container, false);

        listMember = (RecyclerView) rootView.findViewById(R.id.listMember);

        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        linearLayoutManager = new LinearLayoutManager(context);
        memberListAdapter = new MemberListAdapter();

        listMember.setLayoutManager(linearLayoutManager);
        listMember.setAdapter(memberListAdapter);
        listMember.addOnScrollListener(recyclerViewOnScrollListener);

        initData();
        initListener();
    }

    private void initData(){
        List<Member> memberList = new ArrayList<>();
        Member member;

        for(int i=0; i < PAGE_SIZE; i++){
            member = new Member();

            member.setId(i+1);
            member.setName(name[i]);
            member.setTeam(motto[i]);
            member.setThumb(thumb[i]);

            memberList.add(member);
        }

        memberListAdapter.addAll(memberList);

    }

    private void loadData(){
        isLoading = false;

        List<Member> memberList = new ArrayList<>();
        Member member;

        int index = memberListAdapter.getItemCount() - 1;
        int end = index + PAGE_SIZE;

        if (end <= thumb.length) {
            for (int i = index; i < end; i++) {
                member = new Member();

                member.setId(i + 1);
                member.setName(name[i]);
                member.setTeam(motto[i]);
                member.setThumb(thumb[i]);

                memberList.add(member);
            }
            memberListAdapter.addAll(memberList);
            if(end >= thumb.length){
                memberListAdapter.setLoading(false);
            }
        }

    }

    private void initListener() {
        memberListAdapter.setOnItemClickListener(new MemberListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(context, "Clicked at index "+ position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    private RecyclerView.OnScrollListener recyclerViewOnScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            int visibleItemCount = linearLayoutManager.getChildCount();
            int totalItemCount = linearLayoutManager.getItemCount();
            int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();

            if (!isLoading && !isLastPage) {
                if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
                        && firstVisibleItemPosition >= 0
                        && totalItemCount >= PAGE_SIZE) {
                    isLoading = true;

                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            loadData();
                        }
                    }, 2000);
                }
            }
        }
    };
}

Deploy dan jalankan maka hasilnya seperti ini, terlihat progressbar dibagian bawah.
*sory kalau TS nya ngidol :v


Source code lengkap dapat dilihat di https://github.com/wimsonevel/AndroidPagingRecyclerView

Sekian dan semoga bermanfaat.
Happy Coding :)

Share this :

Previous
Next Post »
13 Komentar
avatar

Mas bila pada recyclerviewnya saat diklik?setonclicklinstener maka akan menampilkan detail datanya, apa ada tutorialnya. Makasih

Balas
avatar

ada gan. Coba lihat di sini ada contoh recyclerview bisa di klik http://wimsonevel.blogspot.co.id/2016/05/tutorial-android-tutorial-crud-with.html

Balas
avatar

Untuk RecyclerView yang ini untuk menambahkan aksi click bagaimana mas?

Namba coding dibagian mana saja?
Thanks

Balas
avatar

udah ditambahkan ditutorial di atas gan.. bisa dicek lagi..

Balas
This comment has been removed by the author. - Hapus
avatar

emm mas apa fungsi variable isLoading dan isLastPage ?? kok kayaknya gak di pake buat apa apa deh ??

yang di bagian method onScrolled expresi pertama yang "isLoading && isLastPage" kayaknya gak perlu di pake juga bisa deh soalnya udah pasti hasil akan selalu false.

Balas
avatar

iya gan cuma pengecekan tambahan aja hehe.., kalau datanya dinamis misal dari API baru pake itu gan..

Balas
avatar

mas, kalo saya implementasikan load data dari server.
itu berarti diwebnya gak perlu dibuat paging atau bgmana?

btw tQ semua artikel nya bagus

Balas
avatar

di web gak perlu, cukup select datanya per limit di database pake query.. nanti saya buatin tutorial load data dari server.. thanks :)

Balas
avatar

Terima kasih mas, Tutorialnya berhasil. Tapi gimana kalo load data nya lewat Web Service? Untuk page per limitnya itu di setting di Adapternya atau lewat Database ya?

Balas
avatar

dua2nya gan, setting limit di database, kalo page di adapter. Bisa dilihat contoh projectnya disini https://wimsonevel.blogspot.co.id/2017/07/re-tutorial-android-http-client-on.html

Balas

Penulisan markup di komentar
  • Silakan tinggalkan komentar sesuai topik. Komentar yang menyertakan link aktif, iklan, atau sejenisnya akan dihapus.
  • Untuk menyisipkan kode gunakan <i rel="code"> kode yang akan disisipkan </i>
  • Untuk menyisipkan kode panjang gunakan <i rel="pre"> kode yang akan disisipkan </i>
  • Untuk menyisipkan quote gunakan <i rel="quote"> catatan anda </i>
  • Untuk menyisipkan gambar gunakan <i rel="image"> URL gambar </i>
  • Untuk menyisipkan video gunakan [iframe] URL embed video [/iframe]
  • Kemudian parse kode tersebut pada kotak di bawah ini
  • © 2015 Simple SEO ✔

Ads