[Android] RecyclerView trong Android

Chào các bạn, đã lâu lâu rồi không viết blog, trong bài viết này mình sẽ giới thiệu và hướng dẫn các bạn sử dụng cơ bản về RecyclerView trong Android.

RecyclerView là gì

RecyclerView là một View mới trong android giống như ListView nhưng mạnh mẽ hơn rất nhiều.
RecyclerView cho phép chúng ta load dữ liệu nhiều hơn ListView, vuốt mượt hơn, hiệu ứng đẹp hơn và hỗ trợ đa dạng layout của các phần tử trong danh sách.

Sử dụng RecyclerView trong Eclipse

Không biết máy của các bạn có mạnh để dùng được Android Studio một cách mượt mà không nhưng với “vợ” của mình thì nó có thể bốc cháy khi bật Android Studio. Vì vậy mình dùng Eclipse là đủ rồi. Tuy nhiên thì hầu hết các hướng dẫn bây giờ đều hướng dẫn các bạn làm trên Android Studio nên mình đưa thêm phần này vào cho bạn nào có “cảnh ngộ” giống mình.

Các bạn vào thư mục chứa sdk và tim đến thư mục: sdk\extras\android\m2repository\com\android\support\recyclerview-v7\22.1.1 (cái thư mục 22.1.1 là phiên bản sdk của mình dùng, còn của bạn dùng bản nào thì vào thư mục đó) và các bạn sẽ thấy file recyclerview-v7-22.1.1.aar, bạn copy nó ra chỗ khác, đổi tên nó thành recyclerview-v7-22.1.1.zip (Nếu dùng windows thì nhớ cho hiện đuôi của nó lên) và giải nén ra bạn sẽ thấy 1 file classes.jar, đây là file thư viện chúng ta cần dùng. Bạn có thể đổi tên nó cho dễ nhớ, mình đổi nó thành recyclerview.jar. Bạn copy nó vào thư mục lib trong project là xong.

Sử dụng RecyclerView trong Android Studio

Nếu bạn dùng Android studio thì theo lời thiên hạ đồn, mình chưa có kiểm chứng là bạn thêm dòng sau vào file Gradle:

compile 'com.android.support:recyclerview-v7:21.0.+'

Code tạo Danh sách bằng RecyclerView

Trước tiên các bạn hãy tạo project như bình thường, xong xuôi chúng ta bắt đầu code…

Giao diện XML

Trước tiên lag giao diện của 1 phần tử trong danh sách gồm có text và 1 nút xóa. File item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:paddingLeft="8dp"
    android:paddingRight="8dp" >

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:layout_weight="1" />

    <ImageButton
        android:id="@+id/btn_delete"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:src="@drawable/ic_delete" />

</LinearLayout>

Trong code trên

Sau đó tạo giao diện của Activity gồm 1 EditText nhập text, 1 button Add, và một RecyclerView hiển thị danh sách. File activity_main.xml

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/edit_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="name" />

        <Button
            android:id="@+id/btn_add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add" />
    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

</LinearLayout>

Code xử lý java

Trước tiên chúng ta tạo ra một class Data chứa dữ liệu của 1 phần tử, trong này mình ví dụ có tên thôi. FIle Data.java

package cachhoc.net.samplerecyclerview;

public class Data {
	private String name;

	public Data(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

Tiếp theo, giống như khi tùy biến ListView, chúng ta cần tạo 1 adapter riêng. Và ở đây cũng vậy, chúng ta tạo ra 1 adapter cho Recyclerview. File CustomRecyclerAdapter.java

package cachhoc.net.samplerecyclerview;

import java.util.ArrayList;
import java.util.List;

import cachhoc.net.samplerecyclerview.CustomRecyclerAdapter.RecyclerViewHolder;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;

public class CustomRecyclerAdapter extends
		RecyclerView.Adapter<RecyclerViewHolder> {

	private List<Data> listData = new ArrayList<Data>();

	public CustomRecyclerAdapter(List<Data> listData) {
		this.listData = listData;
	}

	public void updateList(List<Data> data) {
		listData = data;
		notifyDataSetChanged();
	}

	@Override
	public int getItemCount() {
		return listData.size();
	}

	@Override
	public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup,
			int position) {
		LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
		View itemView = inflater.inflate(R.layout.item, viewGroup, false);
		return new RecyclerViewHolder(itemView);
	}

	@Override
	public void onBindViewHolder(RecyclerViewHolder viewHolder, int position) {
		viewHolder.tvName.setText(listData.get(position).getName());
	}

	public void addItem(int position, Data data) {
		listData.add(position, data);
		notifyItemInserted(position);
	}

	public void removeItem(int position) {
		listData.remove(position);
		notifyItemRemoved(position);
	}

	/**
	 * ViewHolder for item view of list
	 * */

	public class RecyclerViewHolder extends RecyclerView.ViewHolder implements
			OnClickListener {

		public TextView tvName;
		public ImageButton btnDelete;

		public RecyclerViewHolder(View itemView) {
			super(itemView);
			tvName = (TextView) itemView.findViewById(R.id.tv_name);
			btnDelete = (ImageButton) itemView.findViewById(R.id.btn_delete);

			// set listener for button delete
			btnDelete.setOnClickListener(this);
		}

		// remove item when click button delete
		@Override
		public void onClick(View v) {
			removeItem(getAdapterPosition());
		}
	}

}

Trong code trên các bạn để ý một chút, nó khác ListView đó.
Phương thức onCreateViewHolder có chức năng tương tự getView khi dùng ListView, nó để tìm đến giao diện của 1 phần tử, chính là item.xml đã xây dựng bên trên nhưng khi trả về chúng ta trả về RecyclerViewHolder.

Phương thức onBindViewHolder được gọi để đặt các giá trị trong các phần tử.

RecyclerViewHolder là 1 class chứa các thuộc tính mà một phần tử có (text name và button delete). Trong RecyclerViewHolder các bạn cũng chú ý là chúng ta bắt sự kiện cho button delete tại đây chứ không bắt trong onCreateViewHolder vì khi bắt sự kiện chúng ta cần biết vị trí (position) thông qua phương thức getAdapterPosition chứ không nên bắt trong onCreateViewHolder sẽ dẫn đến sai sót.

Cuối cùng là viết code cho MainActivity. Cái này thì dễ rùi. File MainActivity.java

package cachhoc.net.samplerecyclerview;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {

	private RecyclerView recyclerView;
	private CustomRecyclerAdapter adapter;
	private RecyclerView.LayoutManager layoutManager;

	private EditText editName;

	private List<Data> listData = new ArrayList<Data>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// connect views.
		editName = (EditText) findViewById(R.id.edit_name);
		recyclerView = (RecyclerView) findViewById(R.id.recycler);

		// If the size of views will not change as the data changes.
		recyclerView.setHasFixedSize(true);

		// Setting the LayoutManager.
		layoutManager = new LinearLayoutManager(this);
		recyclerView.setLayoutManager(layoutManager);

		// Setting the adapter.
		adapter = new CustomRecyclerAdapter(listData);
		recyclerView.setAdapter(adapter);

		// set listener for button add
		((Button) findViewById(R.id.btn_add)).setOnClickListener(this);
	}

	// Called when add button is clicked.
	public void addItem() {

		// get data.
		Data dataToAdd = new Data(editName.getText().toString());

		// Update adapter.
		adapter.addItem(listData.size(), dataToAdd);
	}

	@Override
	public void onClick(View v) {
		addItem();
	}
}

Các bạn có thể download project (thực hiện trên eclipse) Sample Recyclerview