In this tutorial, we are going to implement Android RecyclerView infinite scroll. Imagine you have a large data source you plan to load on a RecyclerView adapter, if you bind all the data at once it will certainly affect the smooth scrolling of your app and your app will appear as running slow.
We will implement the concept of android RecyclerView infinite scroll which will load more data into RecyclerView at the end of visible loaded data as we scroll up or down. This way everything works the way they are meant to be.
Before we dive into more details, it is important for us to understand what we are planning to achieve. Below is the screen-shot of the application we will be creating.
Lets start to soil our hands in code. Start up your IDE. For this tutorial, I am using the following tools and environment, feel free to use what works for you.
Windows 7
Android Studio
Sony Xperia ZL
Min SDK 14
Target SDK 23
To create a new android application project, follow the steps as stipulated below.
Go to File menu
Click on New menu
Click on Android Application
Enter Project name: AndroidRecyclerViewInfiniteScroll
Package: com.inducesmile.androidrecyclerviewinfinitescroll
Select Blank Activity
Name your activity : MainActivity
Keep other default selections
Continue to click on next button until Finish button is active, then click on Finish Button.
Strings.xml
We are going to update our project strings.xml file located in the values folder inside the res folder. Open the file and add the code below to it.
android:layout_width="match_parent"
<resources> <string name="app_name">Android RecyclerView Infinite Scroll</string> </resources>
Colors.xml
Open the colors.xml file in the same location as the strings.xml file and add the code below to the file.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorBlack">#000000</color> <color name="colorWhite">#ffffff</color> </resources>
activity_main.xml
Let’s open our project main layout file, we are going to add a RecycerView. Add the code below inside this file.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.inducesmile.androidrecyclerviewinfinitescroll.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" /> </RelativeLayout>
Since we are going use a RecyclerView adapter with the RecyclerView object, we will proceed to create the recyclerview item list layout. This is the layout file that each item on the Recyclerview will use to display its data content.
item_list.xml
Go to the res > layout folder and open item_list.xml file in your environment. Add the code below to the file.
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" card_view:cardCornerRadius="4dp" card_view:cardUseCompatPadding="true" card_view:cardPreventCornerOverlap="true" card_view:cardElevation="4dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/icon_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/sideicon" android:layout_alignParentLeft="true" android:layout_marginLeft="8dp" android:layout_marginTop="18dp" android:adjustViewBounds="true" android:contentDescription="@string/app_name"/> <TextView android:id="@+id/title_header" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/icon_image" android:layout_alignBaseline="@+id/icon_image" android:padding="18dp" android:text="@string/app_name"/> </RelativeLayout> </android.support.v7.widget.CardView>
progress_item.xml
Go the layout folder, right click and choose create new file. Name the file progress_item.xml. This is will be use when we want to add new data in our RecyclerView. It will tell the user that some new data is beginning load. Open the file and add the code below.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar android:id="@+id/progressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminate="true" style="@android:style/Widget.Holo.ProgressBar" android:layout_gravity="center_horizontal"/> </LinearLayout>
RecyclerViewAdapter.java
Now, we will move over to the RecyclerView adapter which will extends RecyclerView.Adapter<RecyclerViewHolders>. In this class, we are going to override three methods getItemViewType(int position), RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) and onBindViewHolder(RecyclerViewHolders holder, int position).
In the constructor, we will pass an instance of the RecyclerView as a parameter and add the addOnScrollListener event. We will override the onScrolled method of this inner class and implement the infinite data loading.
Open this file and add the code below to the file.
import android.content.Context; 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 java.util.List; public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> { private List<String> itemList; protected Context context; private int visibleThreshold = 5; private int lastVisibleItem, totalItemCount; private boolean loading; private OnLoadMoreListener onLoadMoreListener; public RecyclerViewAdapter(Context context, List<String> itemList, RecyclerView recyclerView) { this.itemList = itemList; this.context = context; if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){ final LinearLayoutManager linearLayoutManager = (LinearLayoutManager)recyclerView.getLayoutManager(); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = linearLayoutManager.getItemCount(); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); if(!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)){ if(onLoadMoreListener != null){ onLoadMoreListener.onLoadMore(); } loading = true; } } }); } } @Override public int getItemViewType(int position) { return itemList.get(position) != null ? 1 : 0; } @Override public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerViewHolders viewHolder = null; if(viewType == 1){ View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false); viewHolder = new RecyclerViewHolders(layoutView); }else{ View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false); viewHolder = new ProgressViewHolder(layoutView); } return viewHolder; } @Override public void onBindViewHolder(RecyclerViewHolders holder, int position) { if(holder instanceof RecyclerViewHolders){ ((RecyclerViewHolders)holder).textTitle.setText(itemList.get(position)); }else{ ((ProgressViewHolder)holder).progressBar.setIndeterminate(true); } } public void setLoad(){ loading = false; } @Override public int getItemCount() { return this.itemList.size(); } public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener){ this.onLoadMoreListener = onLoadMoreListener; } public interface OnLoadMoreListener { void onLoadMore(); } public void setLoaded() { loading = false; } }
If you remember, we create two layout files for our adapter class, one for the item list and the other for the progressbar. Since we will use the View Holder pattern in the adapter, we will create two different classes that will extends from the RecyclerView.Holder class.
RecyclerViewHolders.java
Go to your project package folder, right click and choose create a new file. Name the file RecyclerViewHolders.java. Open this file and paste the code below inside this file.
import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class RecyclerViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener{ public ImageView displayedImage; public TextView textTitle; public RecyclerViewHolders(View itemView) { super(itemView); itemView.setOnClickListener(this); textTitle = (TextView)itemView.findViewById(R.id.title_header); } @Override public void onClick(View view) { } }
ProgressViewHolder.java
We will follow the same procedure as above to create this file. Once you have created it, open the file and paste the code below inside the file.
import android.view.View; import android.widget.ProgressBar; public class ProgressViewHolder extends RecyclerViewHolders{ public ProgressBar progressBar; public ProgressViewHolder(View itemView) { super(itemView); progressBar = (ProgressBar)itemView.findViewById(R.id.progressBar); } }
MainActivity
Finally, we will go to our MainActivity.java file. This is the activity file that will make use of the main layout file we added a RecyclerView to.
We will get the instance of the RecyclerView, set a LinearLayourManager object to it. In the setAdapter method of the class , we will pass an instance of the RecyclerView Adapter we created.
Open this file and add the below code inside the file.
import android.os.Bundle; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private RecyclerView recyclerView; private RecyclerViewAdapter recyclerViewAdapter; private LinearLayoutManager linearLayoutManager; private List<String> adapterData; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler = new Handler(); linearLayoutManager = new LinearLayoutManager(MainActivity.this); // return the data object adapterData = getFirstData(); recyclerView = (RecyclerView)findViewById(R.id.recycler_view); recyclerView.setLayoutManager(linearLayoutManager); recyclerViewAdapter = new RecyclerViewAdapter(MainActivity.this, adapterData, recyclerView); recyclerView.setAdapter(recyclerViewAdapter); recyclerViewAdapter.setOnLoadMoreListener(new RecyclerViewAdapter.OnLoadMoreListener() { @Override public void onLoadMore() { adapterData.add(null); recyclerViewAdapter.notifyItemInserted(adapterData.size() - 1); handler.postDelayed(new Runnable() { @Override public void run() { adapterData.remove(adapterData.size() - 1); recyclerViewAdapter.notifyItemRemoved(adapterData.size()); for (int i = 0; i < 15; i++) { adapterData.add("Item" + (adapterData.size() + 1)); recyclerViewAdapter.notifyItemInserted(adapterData.size()); } recyclerViewAdapter.setLoaded(); } }, 2000); System.out.println("load"); } }); } private List<String> getFirstData(){ List<String> listObject = new ArrayList<String>(); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); listObject.add("one"); return listObject; } }
This brings us to the end of this tutorial. I hope that you have learn something. The next tutorial will be on Android RecyclerView Infinite Scroll.
You can download the code for this tutorial below. If you are having hard time downloading the tutorials, kindly contact me.
Remember to subscribe with your email address so that you will be among the first to receive my new android blog post once it is published.
Please if you love this tutorial, kindly download my android app – Complete Mathematics – in Google Play Store and let me know what you think about it.
hello henry.
i want to beg you source code.
that is infinite recyclerview with gson.
i read your two tutorial, infinite recyclerview and gson.
but can’t combine to one.
may i ask?
please could you give me infinite recyclerview with gson source code? you made.
help me please.
crimy2000@naver.com
i’m working on it for long days, couldnt solve this problem yet.
have a nice day.
You did not say how you want to combine them.
Hey Henry,
My friend choco1004 wants to know how to fetch data from a database using GSON while implementing the infinite scroll function simultaneously. Android is a weak language for both of us but any help on this matter would be much appreciated!
Thank you,
Ethan
Where is the download link
This code does not work well
You can add these codes
thank you .
textbody = (TextView)itemView.findViewById(R.id.body_header);