Trước khi tìm hiểu RecyclerView
nên đọc lại 3 bài viết về ListView
từ cơ bản tới nâng cao:
- ListView trong Android - Phần 1
- ListView trong Android - Phần 2
- ListView Multiple Selection và ListView Single Selection trong Android
RecyclerView so với ListView
So với ListView
thì RecyclerView
có những điểm mạnh mẽ vượt trội hơn như sau:
ListView
không cần sử dụng ViewHolder pattern để cải thiện hiệu suất củaListView
. Nhưng ngược lại, khi tạo 1 Adapter sử dụng vớiRecyclerView
, bắt buộc phải sử dụng ViewHolder để cải thiện hiệu suất.- Mục đích sử dụng ViewHolder, để tái sử dụng View, nhằm tránh việc tạo View mới và
findViewById
quá nhiều. ListView
chỉ hỗ trợ danh sách dạng cuộn dọc,RecylerView
cung cấpRecyclerView.LayoutManager
cho phép layout các item trongListView
theo các kiểu khác nhau (ngang, dọc, dạng lưới, dạng staggered grid).- Xử lý animation cho các item trong
ListView
không dễ dàng nhưngRecyclerView
có hỗ trợItemAnimator
giúp xử lý animation khi thêm vào hay xóa 1 item ra khỏi Recycler 1 cách dễ dàng. Mặc địnhRecyclerView
, sử dụngDefaultItemAnimator
. ListView
sử dụng divider không được linh hoạt nhưng vớiRecylerView
có hỗ trợItemDecoration
, cho phép vẽ divider 1 cách tùy thích.ListView
hỗ trợ các phương thứcsetOnItemClickListener()
vàsetOnLongItemListener()
để chọn 1 item trongListView
.RecylerView
chỉ hỗ trợ 1 phương thứconItemTouchListener()
.
Các thành phần khi sử dụng RecyclerView
Khi sử dụng RecyclerView
phải làm việc với những thành phần sau đây:
RecyclerView.Adapter
Đây là thành phần xử lý dữ liệu collecion (dữ liệu kiểu danh sách) và bind (gắn) những dữ liệu này, lên các item của RecyclerView
.
Khi tạo custom Adapter phải override lại 2 phương thức chính là:
onCreateViewHolder()
: dùng để tạoView
mới choRecyclerView
, nếuRecyclerView
đã cached lạiView
thì phương thức này sẽ không được gọi.onBindViewHolder()
: dùng gắn dữ liệu vàoView
.
LayoutManager
Là thành phần có chức năng sắp xếp các item trong RecylerView
. Các item cuộn dọc hay ngang đều phụ thuộc vào đặt LayoutManager
cho RecyclerView
.
Các lớp con của LayoutManager
:
LinearLayoutManager
: hỗ trợ cuộn các item theo chiều ngang hay chiều dọc.GridLayoutManager
: layout các item trongRecyclerView
dưới dạng Grid giống như khi sử dụngGridView
.StaggerdGridLayoutManager
: layout các item trongListView
dưới dạng lưới so le.
ItemAnimator
: là thành phần hỗ trợ animation khi thêm vào hay xóa 1 item ra khỏi RecyclerView
. Để tìm hiểu rõ phần này, cần tìm hiểu các lớp sau:
ItemAnimator
: là lớp đại diện cho khung sườn của animation trongRecyclerView
.SimpleItemAnimator
: là lớp wrapper lạiItemAnimator
.DefaultItemAnimator
: lớp xử lý animation mặc định sử dụng trongRecyclerView
.
Sử dụng RecyclerView trong Android
Mặc định RecyclerView
không có sẵn trong Android SDK mà phải import vào thư viện. Chỉ cần dán dòng dưới đây vào build.gradle của module app, sau đó nhấn Sync Now để Android Studio tải và nạp thư viện tự động.
compile 'com.android.support:recyclerview-v7:23.0.0'
Hoặc cách khác là vào File → Project Structure, chọn module app và chuyển sang tab Dependencies, sau đó nhấn vào dấu +
và chọn Library Dependencies.
Tìm thư viện RecyclerView
, sau đó nhấn OK để import thư viện:

Sau khi đã import thư viện, bắt đầu tìm hiểu cách sử dụng RecyclerView
như sau:
- Tạo model lớp để chứa dữ liệu.
- Thêm
RecyclerView
vào main_activity.xml. - Tạo giao diện cho 1 dòng.
- Tạo custom Adapter và gán dữ liệu cho từng dòng trong Adapter.
- Cài đặt
RecyclerView
trong MainActivity.java.
Bước 1: tạo model để chứa dữ liệu
Lớp Song
đại diện cho 1 bài hát, gồm các thông tin:
mCode
: mã số bài hát.mTitle
: tên bài hát.mLyric
: lời của bài hát.mAstist
: tên ca sĩ.
File Song.java
package com.eitguide.nguyennghia.recyclerviewandroid;
/**
* Created by nguyennghia on 8/25/16.
*/
public class Song {
private String mCode;
private String mTitle;
private String mLyric;
private String mArtist;
public Song() {
// TODO something
}
public Song(String code, String title, String lyric, String artist) {
this.mCode = code;
this.mTitle = title;
this.mLyric = lyric;
this.mArtist = artist;
}
public String getCode() {
return mCode;
}
public String getTitle() {
return mTitle;
}
public String getLyric() {
return mLyric;
}
public String getArtist() {
return mArtist;
}
public void setCode(String code) {
this.mCode = code;
}
public void setTitle(String title) {
this.mTitle = title;
}
public void setLyric(String lyric) {
this.mLyric = lyric;
}
public void setArtist(String artist) {
this.mArtist = artist;
}
}
Bước 2: thêm RecyclerView vào main_activity.xml
File main_activity.java
<?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.eitguide.nguyennghia.recyclerviewandroid.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_songs"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Bước 3: tạo giao diện cho 1 row
File row_item_song.xml trong thư mục layout của project, được thiết kế để hiển thị dòng như hình dưới đây:

Và mã nguồn của file này:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="3dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="3dp">
<FrameLayout
android:id="@+id/fl_code"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true">
<TextView
android:id="@+id/tv_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#19b395"
android:textSize="18dp" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_toRightOf="@+id/fl_code"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="#2c3e50"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_lyric"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="#34495e"
android:textSize="14dp" />
<TextView
android:id="@+id/tv_artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#7f8c8d"
android:textSize="14dp" />
</LinearLayout>
</RelativeLayout>
Bước 4: tạo custom Adapter và gắn dữ liệu cho từng dòng trong Adapter
package com.eitguide.nguyennghia.recyclerviewandroid;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/**
* Created by nguyennghia on 8/25/16.
*/
public class SongAdapter extends RecyclerView.Adapter<SongAdapter.SongViewHolder> {
private static final String TAG = "SongAdapter";
private List<Song> mSongs;
private Context mContext;
private LayoutInflater mLayoutInflater;
public SongAdapter(Context context, List<Song> datas) {
mContext = context;
mSongs = datas;
mLayoutInflater = LayoutInflater.from(context);
}
@Override
public SongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Inflate view from row_item_song.xml
View itemView = mLayoutInflater.inflate(R.layout.row_item_song, parent, false);
return new SongViewHolder(itemView);
}
@Override
public void onBindViewHolder(SongViewHolder holder, int position) {
// Get song in mSong via position
Song song = mSongs.get(position);
//bind data to viewholder
holder.tvCode.setText(song.getCode());
holder.tvTitle.setText(song.getTitle());
holder.tvLyric.setText(song.getLyric());
holder.tvArtist.setText(song.getArtist());
}
@Override
public int getItemCount() {
return mSongs.size();
}
class SongViewHolder extends RecyclerView.ViewHolder {
private TextView tvCode;
private TextView tvTitle;
private TextView tvLyric;
private TextView tvArtist;
public SongViewHolder(View itemView) {
super(itemView);
tvCode = (TextView) itemView.findViewById(R.id.tv_code);
tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
tvLyric = (TextView) itemView.findViewById(R.id.tv_lyric);
tvArtist = (TextView) itemView.findViewById(R.id.tv_artist);
}
}
}
Tạo Custom Adapter trong RecyclerView
dễ dàng hơn so với ListView, chỉ cần tạo 1 lớp kế thừa RecyclerView
. Còn ViewHolder chỉ việc xử lý trong onCreateViewHolder
để tạo mới ViewHolder. Và onBindViewHolder
để gán dữ liệu lấy từ collection vào ViewHolder.
Bước 5: cài đặt RecyclerView trong MainActivity.java
Không giống như ListView
chỉ cần đặt Adapter cho ListView
là đủ. Đối với RecyclerView
phải đặt 2 thành phần bắt buộc dưới đây:
- Đặt adapter cho
RecyclerView
sử dụng phương thứcsetAdapter()
. - Đặt layout manager để muốn layout các item như các kiểu dọc, ngang, lưới, lưới so le bằng cách sử dụng phương thức
setLayoutManager()
.
Mã nguồn MainActivity.java
package com.eitguide.nguyennghia.recyclerviewandroid;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
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 RecyclerView rvSongs;
private SongAdapter mSongAdapter;
private List<Song> mSongs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvSongs = (RecyclerView)findViewById(R.id.rv_songs);
// Create song data
mSongs = new ArrayList<>();
mSongs = new ArrayList<>();
mSongs.add(new Song("60696", "NẾU EM CÒN TỒN TẠI", "Khi anh bắt đầu 1 tình yêu Là lúc anh tự thay", "Trịnh Đình Quang"));
mSongs.add(new Song("60701", "NGỐC", "Có rất nhiều những câu chuyện Em dấu riêng mình em biết", "Khắc Việt"));
mSongs.add(new Song("60650", "HÃY TIN ANH LẦN NỮA", "Dẫu cho ta đã sai khi ở bên nhau Cô yêu thương", "Thiên Dũng"));
mSongs.add(new Song("60610", "CHUỖI NGÀY VẮNG EM", "Từ khi em bước ra đi cõi lòng anh ngập tràng bao", "Duy Cường"));
mSongs.add(new Song("60656", "KHI NGƯỜI MÌNH YÊU KHÓC", "Nước mắt em đang rơi trên những ngón tay Nước mắt em", "Phạm Mạnh Quỳnh"));
mSongs.add(new Song("60685", "MỞ", "Anh mơ gặp em anh mơ được ôm anh mơ được gần", "Trịnh Thăng Bình"));
mSongs.add(new Song("60752", "TÌNH YÊU CHẮP VÁ", "Muốn đi xa nơi yêu thương mình từng có Để không nghe", "Mr. Siro"));
mSongs.add(new Song("60608", "CHỜ NGÀY MƯA TAN", "1 ngày mưa và em khuất xa nơi anh bóng dáng cứ", "Trung Đức"));
mSongs.add(new Song("60603", "CÂU HỎI EM CHƯA TRẢ LỜI", "Cần nơi em 1 lời giải thích thật lòng Đừng lặng im", "Yuki Huy Nam"));
mSongs.add(new Song("60720", "QUA ĐI LẶNG LẼ", "Đôi khi đến với nhau yêu thương chẳng được lâu nhưng khi", "Phan Mạnh Quỳnh"));
mSongs.add(new Song("60856", "QUÊN ANH LÀ ĐIỀU EM KHÔNG THỂ - REMIX", "Cần thêm bao lâu để em quên đi niềm đâu Cần thêm", "Thiện Ngôn"));
mSongAdapter = new SongAdapter(this, mSongs);
rvSongs.setAdapter(mSongAdapter);
RecyclerView scroll vertical
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
rvSongs.setLayoutManager(linearLayoutManager);
}
}
Chú ý đoạn mã:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
Vì muốn RecyclerView
cuộn theo chiều dọc nên sử dụng LinearLayoutManager.VERTICAL
. Nếu muốn cuộn theo chiều ngang thì truyền vào LinearLayoutManager.HORIZONTAL
:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
Sử dụng những lớp sau để setLayoutManager()
cho RecyclerView
:
GridLayoutManager
: layout các item trongRecyclerView
theo dạng lưới.StaggeredLayoutManager
: layout các item trongRecyclerView
theo dạng lưới so le nhau.
Select item trong RecyclerView
Chọn item trong RecyclerView
, bằng cách setOnClickListenner
cho itemView, trong constructor của ViewHolder như sau:
class SongViewHolder extends RecyclerView.ViewHolder {
private TextView tvCode;
private TextView tvTitle;
private TextView tvLyric;
private TextView tvArtist;
public SongViewHolder(View itemView) {
super(itemView);
tvCode = (TextView) itemView.findViewById(R.id.tv_code);
tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
tvLyric = (TextView) itemView.findViewById(R.id.tv_lyric);
tvArtist = (TextView) itemView.findViewById(R.id.tv_artist);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Song song = mSongs.get(getAdapterPosition());
Toast.makeText(mContext, song.getTitle(), Toast.LENGTH_SHORT).show();
}
});
}
}
Tải code sử dụng trong bài viết:
- Tải trực tiếp tại: RecyclerViewAndroid-master.zip.
- Tải thông qua Github.