Ở các bài trước trong Tự học lập trình Android, chúng ta đã tìm hiểu được về một số thành phần cơ bản để lập trình ứng dụng Android như Activity, Fragment, layout .v.v… Trong bài này, chúng ta sẽ tìm hiểu và thực hành sử dụng RecyclerView – một ViewGroup hay được dùng để hiển thị dữ liệu dạng list (danh sách) trong lập trình ứng dụng Android.
{index}
Giới thiệu RecyclerView
RecycleView là một ViewGroup hiển thị dữ liệu dạng danh sách tương tự ListView nhưng có những tiện lợi hơn (do RecyclerView được đưa vào thư viện Android Support Library muộn hơn khá nhiều so với ListView nên có nhiều ưu điểm hơn) ví dụ như:
- Có thể hiển thị danh sách dữ liệu theo chiều dọc, ngang, dạng lưới.
- Có ViewHolder tích hợp sẵn trong Adapter giúp tối ưu hiệu năng xử lý hơn so với ListView không có ViewHolder.
Thực hành sử dụng RecyclerView trong app Android
(Bài viết được lược dịch: https://developer.android.com/guide/topics/ui/layout/recyclerview)
Nếu ứng dụng của bạn cần hiển thị danh sách các tập dữ liệu lớn (hoặc dữ liệu thường xuyên thay đổi), bạn nên sử dụng RecyclerView như được mô tả trong bài này.
Hình 1. Một danh sách sử dụng RecyclerView
Tổng quan về RecyclerView
Widget RecyclerView là phiên bản ListView tiên tiến và linh hoạt hơn.
Trong mô hình RecyclerView, một số thành phần khác nhau hoạt động cùng nhau để hiển thị dữ liệu của bạn. Container tổng thể cho giao diện người dùng của bạn là một đối tượng RecyclerView mà bạn thêm vào bố cục của mình. RecyclerView tự điền vào các khung nhìn (view) được cung cấp bởi trình quản lý bố cục (layout manager) mà bạn cung cấp. Bạn có thể sử dụng một trong những trình quản lý bố cục tiêu chuẩn của chúng ta (chẳng hạn như LinearLayoutManager hoặc GridLayoutManager) hoặc thực hiện riêng của bạn.
Thêm thư viện hỗ trợ
Để truy cập widget RecyclerView, bạn cần thêm v7 Support Libraries vào dự án của mình như sau:
- Mở tệp build.gradle cho mô-đun ứng dụng của bạn.
- Thêm thư viện hỗ trợ
dependencies
:
dependencies {
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
Thêm RecyclerView vào bố cục (layout) của bạn
Bây giờ bạn có thể thêm RecyclerView vào tệp bố cục (layout) của mình. Ví dụ: layout sau sử dụng RecyclerView làm view duy nhất cho toàn bộ layout:
<?xml version="1.0" encoding="utf-8"?>
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Khi bạn đã thêm widget RecyclerView vào layout của mình, kết nối nó trên Activity với các thành phần LayoutManager, RecyclerViewAdapter để hiển thị dữ liệu như sau:
public class MyActivity extends Activity {
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerView.setHasFixedSize(true);
// use a linear layout manager
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
recyclerView.setAdapter(mAdapter);
}
// ...
}
Thêm một Adapter cho RecyclerView
Để cung cấp tất cả dữ liệu của bạn vào danh sách, bạn phải mở rộng lớp RecyclerView.Adapter
. Đối tượng này tạo các views cho các mục dữ liệu (items) và thay thế nội dung của một số views
bằng các mục dữ liệu mới khi mục gốc không còn hiển thị.
Ví dụ mã sau đây cho thấy việc triển khai đơn giản cho một tập dữ liệu bao gồm một chuỗi các strings
được hiển thị bằng các widget TextView
trong RecyclerView.Adapter
:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView textView;
public MyViewHolder(TextView v) {
super(v);
textView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
TextView v = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
...
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.textView.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataset.length;
}
}
Trình layout manager gọi phương thức onCreateViewHolder()
của Adapter
. Phương thức đó cần xây dựng RecyclerView.ViewHolder
và View
mà nó sử dụng để hiển thị nội dung của nó. Loại ViewHolder
phải khớp với loại được khai báo trong lớp Adapter
. Thông thường, nó sẽ đặt View bằng cách inflate tệp bố cục layout XML. Vì view holder chưa được gán cho bất kỳ dữ liệu cụ thể nào, nên phương thức không thực sự đặt nội dung views.
Nếu danh sách cần cập nhật, hãy gọi một phương thức thông báo trên đối tượng RecyclerView.Adapter
, chẳng hạn như notifyItemChanged()
. Trình layout manager sẽ khởi động lại bất kỳ view holders bị ảnh hưởng nào, cho phép dữ liệu của chúng được cập nhật.
Tùy chỉnh RecyclerView của bạn
Bạn có thể tùy chỉnh các đối tượng RecyclerView để đáp ứng nhu cầu cụ thể của bạn. Các lớp tiêu chuẩn cung cấp tất cả các chức năng mà hầu hết các nhà phát triển sẽ cần; trong nhiều trường hợp, tùy chỉnh duy nhất bạn cần làm là thiết kế view cho từng view holder và viết mã để cập nhật các views đó với dữ liệu phù hợp. Tuy nhiên, nếu ứng dụng của bạn có các yêu cầu cụ thể, bạn có thể sửa đổi hành vi tiêu chuẩn theo một số cách, bạn có thể tham khảo thêm tại đây: https://developer.android.com/guide/topics/ui/layout/recyclerview
Chạy ứng dụng và xem kết quả
Như vậy, widget RecyclerView đã được tích hợp vào ứng dụng của bạn để hiển thị dữ liệu dạng danh sách đơn giản. Bạn có thể chạy ứng dụng mới của mình và xem kết quả. Tiếp theo, để xử lý hành động khi người sử dụng click vào 1 item nào đó trong RecyclerView – một vấn đề thường gặp khi lập trình app Android sử dụng RecyclerView – ở đây: https://stackoverflow.com/questions/24471109/recyclerview-onclick . Nó sẽ là một đoạn mã nhỏ, tương tự như sau:
private final OnClickListener mOnClickListener = new MyOnClickListener();
@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
view.setOnClickListener(mOnClickListener);
return new MyViewHolder(view);
}
Phương thức onClick
:
@Override
public void onClick(final View view) {
int itemPosition = mRecyclerView.getChildLayoutPosition(view);
String item = mList.get(itemPosition);
Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}
Tổng kết
Như vậy, qua bài này chúng ta đã tìm hiểu được RecyclerView trong Android, thực hành tích hợp RecyclerView để hiển thị dữ liệu dạng danh sách, xử lý khi người sử dụng click vào item trong RecyclerView. Ngoài nội dung hướng dẫn trên, các bạn có thể tìm hiểu cách tuỳ biến code để RecyclerView hiển thị danh sách dữ liệu theo chiều dọc (Vertical), ngang (Horizontal), dạng lưới (Grid); hoặc một số tuỳ biến hay dùng khác của RecyclerView. Để học và thực hành lập trình Android hiệu quả mời bạn tiếp tục theo dõi các bài tiếp theo trong loạt bài Tự học lập trình Android.