This practical codelab is part of Unit 4: User experience in Mobile Development module. You will get the most value out of this course if you work through the codelabs in sequence:
For the complete list of codelabs in the course, see Blackboard.
For links to all the concept chapters, apps, and slides, see Android Developer Fundamentals (Version 2).
Letting the user display, scroll, and manipulate a list of similar data items is a common app feature. Examples of scrollable lists include contact lists, playlists, saved games, photo directories, dictionaries, shopping lists, and indexes of documents.
In the practical on scrolling views, you use ScrollView to scroll a View or ViewGroup. ScrollView is easy to use, but it's not recommended for long, scrollable lists.
RecyclerView is a subclass of ViewGroup and is a more resource-efficient way to display scrollable lists. Instead of creating a View for each item that may or may not be visible on the screen, RecyclerView creates a limited number of list items and reuses them for visible content.
In this practical you do the following:
RecyclerView to display a scrollable list.You should be able to:
View to a string using getText().onClick() handler to a View.Toast message.RecyclerView class to display items in a scrollable list.RecyclerView as they become visible through scrolling.RecyclerView to display a list of items as a scrollable list and associate click behavior with the list items.RecyclerView.The RecyclerView app demonstrates how to use a RecyclerView to display a long scrollable list of people. You create the dataset (the people), the RecyclerView itself, and the actions the user can take:

Before you can display a RecyclerView, you need data to display. In this task, you will create a new project for the app and a dataset. In a more sophisticated app, your data might come from internal storage (a file, SQLite database, saved preferences), from another app (Contacts, Photos), or from the internet (cloud storage, Google Sheets, or any data source with an API). Storing and retrieving data is a topic of its own covered in the data storage chapter. For this exercise, you will simulate data by creating it in a class called DataSource.
activity_main.xml), and a layout for the Activity content (content_main.xml).  This layout contains a NavHostfragment and there are two fragments called FirstFragment and SecondFragment.In this step you create a LinkedList of 20 Person objects which have been generated at random. A useful source for generating random data, which I have used here, is https://github.com/mdeanda/lorem.
model package called Person and enter the following code:  public class Person {
    String firstName;
    String lastName;
    String phone;
    String email;
    int clickCount;
    public Person(String f, String l, String p, String e) {
        this.firstName = f;
        this.lastName = l;
        this.phone = p;
        this.email = e;
        clickCount = 0;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public void incrementClickCount() {
        this.clickCount++;
    }
    public String simpleDisplay() {
        String clickMsg = "";
        if (clickCount > 0) {
            clickMsg = ". Clicked: " + clickCount + " times";
        }
        return firstName + " " + lastName + clickMsg;
    }
}
firstName, lastName, phone and email property.model package called DataSource and enter the following code:  import java.util.LinkedList;
public class DataSource {
    // testData is a stock of data items to add
    private LinkedList<Person> testData;
    // data will contain the list of data items displayed by the app
    private LinkedList<Person> data;
    private int testDataIndex = 0;
    private static DataSource _instance;
    private DataSource() {
        data = new LinkedList<>();
        testData = new LinkedList<>();
        testData.add(new Person("Andre", "Snow", "(549) 413-0834", "andre.snow@example.com"));
        testData.add(new Person("Maynard", "Shields", "(457) 311-9060", "maynard.shields@example.com"));
        testData.add(new Person("Sherry", "Ellison", "(916) 926-6098", "sherry.ellison@example.com"));
        testData.add(new Person("Lester", "Buckley", "(699) 228-0885", "lester.buckley@example.com"));
        testData.add(new Person("Heriberto", "Pena", "(504) 512-6981", "heriberto.pena@example.com"));
        testData.add(new Person("Hugh", "Coffey", "(446) 273-9747", "hugh.coffey@example.com"));
        testData.add(new Person("Delmar", "Roach", "(730) 122-4126", "delmar.roach@example.com"));
        testData.add(new Person("Ivy", "Bishop", "(765) 253-6871", "ivy.bishop@example.com"));
        testData.add(new Person("Otis", "Estes", "(460) 524-2120", "otis.estes@example.com"));
        testData.add(new Person("Clayton", "Good", "(349) 700-9200", "clayton.good@example.com"));
        testData.add(new Person("Zachary", "Johns", "(775) 689-1912", "zachary.johns@example.com"));
        testData.add(new Person("Dionne", "Wolf", "(137) 269-4844", "dionne.wolf@example.com"));
        testData.add(new Person("Gena", "Barton", "(524) 729-4493", "gena.barton@example.com"));
        testData.add(new Person("Wade", "Johnson", "(711) 885-7832", "wade.johnson@example.com"));
        testData.add(new Person("Glenda", "Briggs", "(984) 407-9968", "glenda.briggs@example.com"));
        testData.add(new Person("Mercedes", "Joseph", "(551) 170-0298", "mercedes.joseph@example.com"));
        testData.add(new Person("Catherine", "Calderon", "(831) 428-5718", "catherine.calderon@example.com"));
        testData.add(new Person("Adan", "Rodriquez", "(519) 708-9057", "adan.rodriquez@example.com"));
        testData.add(new Person("Pierre", "Lindsay", "(905) 407-3679", "pierre.lindsay@example.com"));
        testData.add(new Person("Brandon", "Morris", "(110) 702-1306", "brandon.morris@example.com"));
        for (int i = 0; i< 5; i++) {
            addPerson();
        }
    }
    public static DataSource getInstance() {
        if (_instance == null) {
            _instance = new DataSource();
        }
        return _instance;
    }
    public void addPerson() {
        // copy a Person from testData to data
        data.add(testData.get(testDataIndex));
        // update to the next index, reset to 0 if at the end of the list
        // some Person objects may be added twice if you add a lot of data
        testDataIndex = (testDataIndex + 1) % testData.size();
    }
    public LinkedList<Person> getData() {
        return data;
    }
}
This class follows the singleton design pattern and has a method that will return a LinkedList<Person> of data.  Our DataSource keeps a stock of data in a LinkedList called testData and will copy items from that list into the LinkedList called data which will contain the actual data displayed by the app.  Adding a new data item will simply copy the next Person from testdata into data.  Our testData acts as a mock source of real data.
private final LinkedList mPersonList;
public FirstFragment() {
    super();
    mPersonList = DataSource.getInstance().getData();
}
 For this practical, you will use a FAB to generate a new Person to insert into the list. The Basic Activity template provides a FAB, but you may want to change its icon. As you learned in another lesson, you can choose an icon from the set of icons in Android Studio for the FAB. Follow these steps:
In this practical, you display data in a RecyclerView. You need the following:
DataSource.RecyclerView for the scrolling list that contains the list items.View elements. RecyclerView requires an explicit layout manager to manage the arrangement of list items contained within it. This layout could be vertical, horizontal, or a grid. You will use a vertical LinearLayoutManager.RecyclerView. It prepares the data in a RecyclerView.ViewHolder. You will create an adapter that inserts into and updates your generated data in your views.ViewHolder that contains the View information for displaying one item from the item's layout.The diagram below shows the relationship between the data, the adapter, the ViewHolder, and the layout manager. 
To implement these pieces, you will need to:
RecyclerView element to the FirstFragment XML content layout (fragment_first.xml) for the RecyclerViews app.personlist_item.xml) for one list item, which is a PersonListItem.PersonListAdapter) with a ViewHolder (PersonViewHolder). Implement the method that takes the data, places it in the ViewHolder, and lets the layout manager know to display it.onViewCreated() method of FirstFragment, create a RecyclerView and initialize it with the adapter and a standard layout manager.Let's do these one at a time.
To add a RecyclerView element to the XML layout, follow these steps:
Button at the center of a ConstraintLayout.TextView and Button elements with the following:  <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
RecyclerView is part of the Androidx Library.The adapter needs the layout for one item in the list. All the items use the same layout. You need to specify that list item layout in a separate layout resource file, because it is used by the adapter, separately from the RecyclerView.
Create a simple Person item layout using a vertical LinearLayout with a TextView:
ConstraintLayout that was created with the file with a LinearLayout using the following code:  <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="6dp">
</LinearLayout>
<TextView
        android:id="@+id/person"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:textStyle="bold"/>
You can use styles to allow elements to share groups of display attributes. An easy way to create a style is to extract the style of a UI element that you already created. To extract the style information for the word TextView in personlist_item.xml:
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="6dp">
    <TextView
        android:id="@+id/person"
        style="@style/person_title" />
</LinearLayout>
Android uses adapters (from the Adapter class) to connect data with View items in a list. There are many different kinds of adapters available, and you can also write custom adapters. In this task you will create an adapter that associates your list of words with word list View items.
To connect data with View items, the adapter needs to know about the View items. The adapter uses a ViewHolder that describes a View item and its position within the RecyclerView.
First, you will build an adapter that bridges the gap between the data in your person list and the RecyclerView that displays it:
PersonListAdapter the following signature:  public class PersonListAdapter extends
        RecyclerView.Adapter<PersonListAdapter.PersonViewHolder> {
}
PersonListAdapter extends a generic adapter for RecyclerView to use a View holder that is specific for your app and defined inside PersonListAdapter. PersonViewHolder shows an error, because you have not yet defined it.OK.Android Studio creates empty placeholders for all the methods. Note how onCreateViewHolder and onBindViewHolder both reference the PersonViewHolder, which hasn't been implemented yet.
To create the ViewHolder, follow these steps:
PersonListAdapter class, add a new WordViewHolder inner class with this signature:  class PersonViewHolder extends RecyclerView.ViewHolder {}
PersonViewHolder inner class for the TextView and the adapter:  public final TextView personItemView;
final PersonListAdapter mAdapter;
WordViewHolder, add a constructor that initializes the ViewHolder TextView from the person XML resource, and sets its adapter:  public PersonViewHolder(View itemView, PersonListAdapter adapter) {
    super(itemView);
    personItemView = itemView.findViewById(R.id.person);
    this.mAdapter = adapter;
}
FirstFragment.java.  Open FirstFragment.java and edit the onViewCreated method to delete the code after the call to the super method.  After you have done that, the method should look like this:  public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
}
You need to hold your data in the adapter, and PersonListAdapter needs a constructor that initializes the word list from the data. Follow these steps:
private LinkedList<Person> mPersonList;
@Override
public int getItemCount() {
    return mPersonList.size();
}
PersonListAdapter needs a constructor that initializes the person list from the data. To create a View for a list item, the PersonListAdapter needs to inflate the XML for a list item. You use a layout inflator for that job. LayoutInflator reads a layout XML description and converts it into the corresponding View items. Start by creating a member variable for the inflater in PersonListAdapter:  private LayoutInflater mInflater;
PersonListAdapter. The constructor needs to have a context parameter, and a linked list of Person with the app's data. The method needs to instantiate a LayoutInflator for mInflater and set mPersonList to the passed in data:  public PersonListAdapter(Context context, 
                               LinkedList<Person> personList) {
   mInflater = LayoutInflater.from(context);
   this.mPersonList = personList;
}
onCreateViewHolder() method and complete it with this code:  @Override
public PersonListAdapter.PersonViewHolder onCreateViewHolder(@NonNull ViewGroup parent, 
                                                             int viewType) {
    View mItemView = mInflater.inflate(R.layout.personlist_item,
            parent, false);
    return new PersonViewHolder(mItemView, this);
}
onCreateViewHolder() method is similar to the onCreate() method. It inflates the item layout, and returns a ViewHolder with the layout and the adapter.onBindViewHolder() method and complete it with the code below:  @Override
public void onBindViewHolder(@NonNull PersonListAdapter.PersonViewHolder holder, 
                             int position) {
    Person person = mPersonList.get(position);
    String mCurrent = person.simpleDisplay();
    holder.personItemView.setText(mCurrent);
}
onBindViewHolder() method connects your data to the view holder.Now that you have an adapter with a ViewHolder, you can finally create a RecyclerView and connect all the pieces to display your data.
private RecyclerView mRecyclerView;
private PersonListAdapter mAdapter;
onViewCreated() method of FirstFragment, add the following code (after the call to super.onViewCreated) that creates the RecyclerView and connects it with an adapter and the data. The comments explain each line.  // Get a handle to the RecyclerView.
mRecyclerView = view.findViewById(R.id.recyclerview);
// Create an adapter and supply the data to be displayed.
mAdapter = new PersonListAdapter(getContext(), mPersonList);
// Connect the adapter with the RecyclerView.
mRecyclerView.setAdapter(mAdapter);
// Give the RecyclerView a default layout manager.
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

Looking at lists of items is interesting, but it's a lot more fun and useful if your user can interact with them. To see how the RecyclerView can respond to user input, you will attach a click handler to each item. When the item is tapped, the click handler is executed, and the full contact details of that person will be displayed in the second fragment.
The list of items that a RecyclerView displays can also be modified dynamically—it doesn't have to be a static list. There are several ways to add additional behaviors. One is to use the floating action button (FAB). For example, in Gmail, the FAB is used to compose a new email. For this practical, you will generate a new contact to insert into the list.
class PersonViewHolder extends RecyclerView.ViewHolder 
        implements View.OnClickListener {
onClick() method.// Get the position of the item that was clicked.
int mPosition = getLayoutPosition();
// Use that to access the affected item in mPersonList.
Person p = mPersonList.get(mPosition);
// Register the click on the person
p.incrementClickCount();
// Notify the adapter, that the data has changed so it can
// update the RecyclerView to display the data.
mAdapter.notifyDataSetChanged();
onClickListener with the View. Add this code to the PersonViewHolder constructor (below the this.mAdapter = adapter line):  itemView.setOnClickListener(this);
In this task you will implement an action for the FAB to:
Follow these steps:
MainActivity.  We can get access to the FAB once this fragment has started.  Add the following onStart lifecycle method to your FirstFragment:  @Override
public void onStart() {
    super.onStart();
    getActivity().findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            DataSource.getInstance().addPerson();
            mAdapter.notifyDataSetChanged();
        }
    });
}
MainActivity and add an OnClickListener.  The listener has a single method called onClick which will tell our DataSource to add a Person to the list and then notify our adapter that its data set has changed.  The call to notifyDataSetChanged is important because otherwise the view will not be updated and the newly added data will not be seen.Challenge 1: Change the options menu to show only one option: Reset. This option should return the list of people to its original state of five people, with nothing clicked and no extra people.
Challenge 2: Creating a click listener for each item in the list is easy, but it can hurt the performance of your app if you have a lot of data. Research how you could implement this more efficiently. This is an advanced challenge. Start by thinking about it conceptually, and then search for an implementation example
View for each list item, the adapter inflates an XML layout resource for a list item using LayoutInflator.RecyclerView layout manager that shows items in a vertical or horizontal scrolling list.RecyclerView layout manager that shows items in a gridRecyclerView layout manager that shows items in a staggered grid.RecyclerView. It prepares the data in a RecyclerView.ViewHolder that describes a View item and its position within the RecyclerView.The related concept documentation is 4.5: RecyclerView.
Android Studio documentation:
Android developer documentation:
RecyclerView Animations and Behind the Scenes (Android Dev Summit 2015)