Làm quen với RecyclerView và CardView trên Android
Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)
Nếu bạn hứng thú với việc xây dựng một ứng dụng Android sử dụng các danh sách để hiển thị dữ liệu, thì Android Lollipop có hai sự lựa chọn mới để làm cho công việc của bạn dễ dàng hơn, đó là RecyclerView
và CardView
. Sử dụng những thành phần này, giúp cho ứng dụng của bạn có một giao diện phù hợp với các nguyên tắc được đề cập trong đặc tả Material Design của Google.
Yêu cầu
Để thực hiện theo, bạn nên sử dụng phiên bản mới nhất của Android Studio. Bạn có thể tải nó từ trang web Nhà phát triển Android.
1. Hỗ trợ các phiên bản cũ hơn
Tại thời điểm bài viết, có ít hơn 2% thiết bị Android chạy Android Lollipop. Tuy nhiên, nhờ Support Library v7, bạn có thể sử dụng các thành phần RecyclerView
và CardView
trên các thiết bị chạy phiên bản cũ của Android bằng cách thêm các dòng sau vào phần dependencies trong tập tin build.grade của dự án:
compile 'com.android.support:cardview-v7:21.0.+' compile 'com.android.support:recyclerview-v7:21.0.+'
2. Tạo một CardView
Một CardView
là một ViewGroup
. Giống như bất kỳ ViewGroup
nào khác, nó có thể được thêm vào Activity
hoặc Fragment
của bạn bằng cách sử dụng một tập tin layout XML.
Để tạo một CardView
rỗng, bạn sẽ cần thêm đoạn code sau vào layout XML của bạn như ở trong đoạn code sau:
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.CardView>
Một ví dụ thực tế hơn, bây giờ chúng ta hãy tạo ra một LinearLayout
và đặt một CardView
bên trong nó. CardView
có thể đại diện, ví dụ, một người và chứa những thứ sau:
- một
TextView
để hiển thị tên của người đó - một
TextView
để hiển thị độ tuổi - một
ImageView
để hiển thị ảnh của người đó
Tập tin XML sẽ trông giống như sau:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" > <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/cv" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/person_photo" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginRight="16dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/person_name" android:layout_toRightOf="@+id/person_photo" android:layout_alignParentTop="true" android:textSize="30sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/person_age" android:layout_toRightOf="@+id/person_photo" android:layout_below="@+id/person_name" /> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout>
Nếu XML này được sử dụng như là layout của một Activity
, với các trường TextView
và ImageView
được thiết lập các giá trị có ý nghĩa, thì đây là cách nó sẽ được hiển thị trên một thiết bị Android:



3. Tạo một RecyclerView
Bước 1: Xác định nó trong một Layout
Sử dụng một đối tượng RecyclerView
thì hơi phức tạp hơn. Tuy nhiên, định nghĩa nó trong một tập tin layout XML là khá đơn giản. Bạn có thể định nghĩa nó trong một layout như sau:
<android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/rv" />
Để có được một tham chiếu cho nó trong Activity
của bạn, sử dụng đoạn code sau:
RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
Nếu bạn chắc chắn kích thước của RecyclerView
sẽ không thay đổi, thì bạn có thể thêm những thứ sau đây để cải thiện hiệu suất:
rv.setHasFixedSize(true);
Bước 2: Sử dụng một LayoutManager
Không giống như một ListView
, một RecyclerView
cần một LayoutManager
để quản lý vị trí các phần tử của nó. Bạn có thể định nghĩa LayoutManager
của riêng bạn bằng cách thừa kế lớp RecyclerView.LayoutManager
. Tuy nhiên, trong hầu hết các trường hợp, bạn có thể chỉ cần sử dụng một trong các lớp con LayoutManager
được định nghĩa sẵn:
LinearLayoutManager
GridLayoutManager
-
StaggeredGridLayoutManager
Trong hướng dẫn này, tôi sẽ sử dụng một LinearLayoutManager
. Lớp con này của LayoutManager
sẽ, theo mặc định, làm cho RecyclerView
của bạn trông giống như một ListView
.
LinearLayoutManager llm = new LinearLayoutManager(context); rv.setLayoutManager(llm);
Bước 3: Xác định dữ liệu
Cũng giống như một ListView
, một RecyclerView
cần một adapter để truy cập dữ liệu của nó. Nhưng trước khi chúng ta tạo ra một adapter, chúng ta hãy tạo ra dữ liệu mà chúng ta có thể làm việc với chúng. Hãy tạo một lớp đơn giản để đại diện cho một người và sau đó viết một phương thức khởi tạo một List
của các đối tượng Person
:
class Person { String name; String age; int photoId; Person(String name, String age, int photoId) { this.name = name; this.age = age; this.photoId = photoId; } } private List<Person> persons; // This method creates an ArrayList that has three Person objects // Checkout the project associated with this tutorial on Github if // you want to use the same images. private void initializeData(){ persons = new ArrayList<>(); persons.add(new Person("Emma Wilson", "23 years old", R.drawable.emma)); persons.add(new Person("Lavery Maiss", "25 years old", R.drawable.lavery)); persons.add(new Person("Lillie Watts", "35 years old", R.drawable.lillie)); }
Bước 4: Tạo một adapter
Để tạo ra một adapter mà một RecyclerView
có thể sử dụng, bạn phải thừa kế RecyclerView.Adapter
. Adapter này thực hiện theo khuôn mẫu view holder, có nghĩa là bạn định nghĩa một lớp tùy biến thừa kế RecyclerView.ViewHolder
. Mô hình này giúp giảm thiểu việc gọi phương thức findViewById
.
Trước đó trong hướng dẫn này, chúng ta đã xác định layout XML cho một CardView
đại diện cho một người. Bây giờ chúng ta sẽ sử dụng lại layout đó. Bên trong hàm xây dựng của ViewHolder
tùy biến của chúng ta, khởi tạo các view thuộc về các phần tử của RecyclerView
.
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder>{ public static class PersonViewHolder extends RecyclerView.ViewHolder { CardView cv; TextView personName; TextView personAge; ImageView personPhoto; PersonViewHolder(View itemView) { super(itemView); cv = (CardView)itemView.findViewById(R.id.cv); personName = (TextView)itemView.findViewById(R.id.person_name); personAge = (TextView)itemView.findViewById(R.id.person_age); personPhoto = (ImageView)itemView.findViewById(R.id.person_photo); } } }
Tiếp theo, thêm một hàm xây dựng adapter tùy biến để nó có một tham chiếu dữ liệu mà RecyclerView
hiển thị. Vì dữ liệu của chúng ta ở trong hình thức của một List
của các đối tượng Person
, nên hãy sử dụng code sau đây:
List<Person> persons; RVAdapter(List<Person> persons){ this.persons = persons; }
RecyclerView.Adapter
có ba phương thức trừu tượng mà chúng ta phải override. Hãy bắt đầu với phương thức getItemCount
. Phương thức này sẽ trả về số phần tử hiện diện trong dữ liệu. Vì dữ liệu của chúng ta ở trong hình thức của một List
, nên chúng ta chỉ cần gọi phương thức size
của đối tượng List
:
@Override public int getItemCount() { return persons.size(); }
Tiếp theo, override phương thức onCreateViewHolder
. Giống như tên gọi của nó, phương thức này được gọi khi ViewHolder
tuỳ biến cần phải được khởi tạo. Chúng ta xác định layout mà mỗi phần tử của RecyclerView
sẽ sử dụng. Điều này được thực hiện bằng cách inflate layout sử dụng LayoutInflater
, truyền đầu ra cho hàm xây dựng của ViewHolder
tùy biến.
@Override public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); PersonViewHolder pvh = new PersonViewHolder(v); return pvh; }
Override onBindViewHolder
để xác định nội dung của mỗi phần tử của RecyclerView
. Phương thức này rất giống với phương thức getView
của một adapter của ListView
. Trong ví dụ của chúng ta, đây là nơi mà bạn phải thiết lập các giá trị của các trường tên, tuổi, và hình ảnh của CardView
.
@Override public void onBindViewHolder(PersonViewHolder personViewHolder, int i) { personViewHolder.personName.setText(persons.get(i).name); personViewHolder.personAge.setText(persons.get(i).age); personViewHolder.personPhoto.setImageResource(persons.get(i).photoId); }
Cuối cùng, bạn cần phải override phương thức onAttachedToRecyclerView
. Còn bây giờ, chúng ta chỉ cần sử dụng cài đặt phương thức này của lớp cha như hình dưới đây.
@Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); }
Bước 5: Sử dụng Adapter
Bây giờ thì adapter đã sẵn sàng, thêm đoạn code sau vào Activity
của bạn để khởi tạo và sử dụng adapter bằng cách gọi hàm xây dựng của adapter và phương thức setAdapter
của RecyclerView
:
RVAdapter adapter = new RVAdapter(persons); rv.setAdapter(adapter);
Bước 6: Biên dịch và chạy
Khi bạn chạy ví dụ RecyclerView
trên một thiết bị Android, bạn sẽ thấy một cái gì đó tương tự như kết quả sau đây.



Tổng kết
Trong hướng dẫn này, bạn đã học cách sử dụng các thành phần CardView
và RecyclerView
đã được giới thiệu trong Android Lollipop. Bạn cũng đã được xem ví dụ về cách sử dụng của các thành phần trong các ứng dụng Material Design. Lưu ý rằng mặc dù một RecyclerView
có thể làm hầu như tất cả mọi thứ mà một ListView
có thể làm, nhưng đối với các tập dữ liệu nhỏ, sử dụng một ListView
vẫn phù hợp hơn vì nó đòi hỏi ít code.
Bạn có thể tham khảo Tài liệu Nhà phát triển Android để biết thêm thông tin về các lớp CardView
và RecyclerView
.