Infinite scrolling using RecyclerView in Android

By xngo on February 25, 2019

Overview

RecyclerView is used when you need to display a long list of items or your data are changing frequently. For my case, I need it to display more than 400 bus numbers in my Android application, iTransit.

The idea behind RecyclerView is it creates just enough items to fill up the visible screen. As the users scroll down, the top items that are out of the screen, are re-used and appended to the bottom with new data. And, vice versa. Hence, allowing users to indefinitely scroll without consuming more memory & processing power than 1 screen. This in turn makes your application much more responsive. There is no perceived waiting time to load more data.

RecyclerView requires 3 components:

  • Layout Manager: Provide to RecyclerView what to display.
  • Adapter: Create and update View Holder.
  • View Holder: Container to hold your items.

Add RecyclerView Support Library

In your app/build.gradle file, add the following dependency:

dependencies {
    implementation 'com.android.support:recyclerview-v7:28.0.0'
}

Add RecyclerView to your layout

In res/layout/activity_main.xml, add the following layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/my_recycler_view"
    android:scrollbars="vertical"
/>

Here is the code in the main activity with all the components together. MainActivity class below will not run until the adapter class is implemented.

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private RecyclerView.Adapter myAdapter;
    private RecyclerView.LayoutManager layoutManager;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
 
        // If you know that changes in content don't change the layout size,
        //  then set to true. RecyclerView will not waste time to recalculate the layout size.
        recyclerView.setHasFixedSize(true);
 
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
 
        // MyAdapter is not yet implemented.
        myAdapter = new MyAdapter(this.getDataSet());
        recyclerView.setAdapter(myAdapter);
    }
 
    // Fetch data.
    private ArrayList<String> getDataSet(){
        ArrayList<String> longList = new ArrayList<String>();
        for(int i=0; i<400; i++)
            longList.add(String.valueOf(i));
        return longList;
    }
}

Add MyAdapter class

MyAdapter class also contains the implementation of MyViewHolder class. Read through the code. It is self explanatory.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    //--------------- MyViewHolder implementation starts here ---------------------
    // Provide definition of what it holds and allow MyAdapter
    //  to access all the data.
    public static class MyViewHolder extends RecyclerView.ViewHolder {
        public Button button; // Give MyAdapter access.
 
        public MyViewHolder(Button btn) {
            super(btn);
            this.button = btn;
        }
    }
 
    //--------------- MyAdapter implementation starts here ---------------------
    private ArrayList<String> dataSet; // Data source.
 
    public MyAdapter(ArrayList<String> dataSet) {
        this.dataSet = dataSet;
    }
 
    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 
        // Create a new button and put it in the ViewHolder for shipping to the Layout Manager.
        Button btn = new Button(parent.getContext());
        MyViewHolder myViewHolder = new MyViewHolder(btn);
        return myViewHolder;
    }
 
    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        // How do you want to update the content.
        //  MyAdapter access member(button) of MyViewHolder.
        holder.button.setText(this.dataSet.get(position));
    }
 
    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return this.dataSet.size();
    }
}

Screenshot

Simple RecyclerView screenshot

Github

  • https://github.com/xuanngo2001/android-recyclerview-simple

About the author

Xuan Ngo is the founder of OpenWritings.net. He currently lives in Montreal, Canada. He loves to write about programming and open source subjects.