Learn Android — RecyclerView
The world’s most popular mobile OS — from phones and watches to cars and TVs.
Welcome to the Learn Android series. I’m going to share with you, weekly, why and how to start with Android and build your portfolio. I’ll share with you explanations and code snippets on how to implement the most important and basic things in Android.
In the previous article, we learned how to navigate from one activity to another and how different types of Intents are able to perform different types of tasks. We also learned how to pass data between activities through Intents. In this article, we’ll learn how to implement a scrolling list or grid layout using RecyclerView.
Why RecyclerView? To present a list or grid of mostly similar items, each with similar set of views, allowing us to create a rich experience of typography, colors, images, and more. For a large number of similar items, like in the Instagram app, we cannot have a single view component — because then we’ll have to handle all the requirements operation for each view and since we won’t know the number of views generated dynamically, it’s not possible to handle all that. Also, since all these views will be in the memory all at once, the Android system will soon run out of memory. That is why we need an efficient system model like RecyclerView, to handle large datasets.
So how does RecyclerView help? Instead of creating a view component for each of the list item, the RecyclerView keeps some of the views in a queue for reuse. So, the only active views are what can be seen on the screen and a few views above and below it. When we scroll downwards for example, the views at the top are discarded with respect to their data and added to the queue, while the views from the queue are retrieved and binded with the new data and added to the vertical scroll. This is the most simple explanation which depicts what happens on scroll.
To add RecyclerView to your Android project, follow the steps below —
- Click on “Build” → “Edit Libraries and Dependencies”.
- Click on the “+” button.
- Search “recycler” or find in the list below.
- Then select “com.android.support:recyclerview-v7:x.x.x” and Sync the gradle project.
How is RecyclerView different from ListView?
RecyclerView has two additional components in ViewHolder and LayoutManager, which makes all of its components completely modular. These components make it more efficient and flexible compared to other dynamic views.
In the previous article, we saw that the Adapters for the ListView created by extending the ArrayAdapter class overrides the getView() method. But in the RecyclerView, we create the ViewHolder component. In the getView() method, the Adapter for the ListView inflates the layout everytime it is called. But in the RecyclerView we create a ViewHolder which allows us to implement two different functions compared to a single getView() function —
- onCreateViewHolder()
- onBindViewHolder()
These methods help the Android system cache the view components so that there are no repeated calls to findViewById() method like in the adapter we’ve seen in the previous article. The onCreateViewHolder() method inflates the data whereas the onBindViewHolder() binds the data from the data source to the views. Since these calls are reduced, the efficiency increases and thus just the data needs to be recycled and not the whole view component.
Furthermore, the LayoutManager allows customizing the view layouts dynamically with respect to the user preferences or with respect to the device sizes and more. It has 3 main types of layouts — Linear, Grid and Staggered Grid. Linear can be both horizontal or vertical.
Now let’s see how the implementation of RecyclerView works —
First of all the Object class and the item view XML remains the same. Next up, instead of adding ListView in the activity layout, we add the RecyclerView component. Then we implement the Adapter. Let’s code the Adapter for a movie app which displays all it’s trailers in a RecyclerView —
public class TrailerAdapter extends RecyclerView.Adapter<TrailerAdapter.TrailerViewHolder> {
private Context context;
private List<TrailerItem> trailerItemList;
public TrailerAdapter(Context context, List<TrailerItem> trailerItemList) {
this.context = context;
this.trailerItemList = trailerItemList;
}
public class TrailerViewHolder extends RecyclerView.ViewHolder {
public TextView trailerName;
public TrailerViewHolder(View view) {
super(view);
trailerName = view.findViewById(R.id.trailer_name);
}
}
@NonNull
@Override
public TrailerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_trailers, parent, false);
return new TrailerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull TrailerViewHolder holder, int position) {
TrailerItem trailerItem = trailerItemList.get(position);
holder.trailerName.setText(trailerItem.getName());
}
@Override
public int getItemCount() {
return trailerItemList.size();
}
}
Note our class extends RecyclerView.Adapter<ViewHolder> i.e. the Adapter with ViewHolder as a parameter and the ViewHolder contains the view that we’ve inflated.
Notice that onCreateViewHolder() just creates the view whereas we do all the data operations inside the onBindViewHolder() method. Also note that it is a must to implement the getItemCount() method which returns the number of dynamic view items that will be generated.
Now let’s see how to use LayoutManager in the Activity class —
public class DetailActivity extends AppCompatActivity {
private RecyclerView trailersRecycler;
private List<TrailerItem> trailerItemList;
private TrailerAdapter trailerAdapter;
private String TRAILER_URL;@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
//Initialising all the variables with respect to trailer components.
trailerLabel = findViewById(R.id.trailer_label_detail);
trailerItemList = new ArrayList<>();
trailersRecycler = findViewById(R.id.trailers_recycler);
trailerAdapter = new TrailerAdapter(getApplicationContext(), trailerItemList);
TRAILER_URL = getApplicationContext().getResources().getString(R.string.trailerUrl);
//Setting up the trailers recycler view.
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
trailersRecycler.setLayoutManager(layoutManager);
trailersRecycler.setAdapter(trailerAdapter);
}
Notice, that we’ve created a LayoutManager component and set it to a LinearLayoutManager in a horizontal fashion. Also, we create an instance of the adapter and attach the adapter to the RecyclerView. We can populate the TrailerItem ArrayList to view the RecylerView in action.