Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Làm việc với RecyclerView trong ứng dụng Android

Giới thiệu

RecyclerView là widget hiện đại, linh hoạt và hiệu suất cao để hiển thị danh sách lớn (list/grid) trong Android, thay thế ListView cũ. Bài viết hướng dẫn triển khai đầy đủ: Model, Adapter, ViewHolder, LayoutManager.

Các bước thực hiện

Bước 1: Tạo dự án mới

Android Studio → File → New Project → Empty Activity.

Bước 2: Layout chính (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/rlMain"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Bước 3: Model (src/MovieModel.java)

package app.com.sample;

public class MovieModel {
    private String title, genre, year;

    public MovieModel() {}

    public MovieModel(String title, String genre, String year) {
        this.title = title;
        this.genre = genre;
        this.year = year;
    }

    // Getters & Setters
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getYear() { return year; }
    public void setYear(String year) { this.year = year; }
    public String getGenre() { return genre; }
    public void setGenre(String genre) { this.genre = genre; }
}

Bước 4: Item Layout (res/layout/movies_list.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:layout_margin="8dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_toStartOf="@id/year"
            android:textColor="#222222"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:textColor="#999999" />

        <TextView
            android:id="@+id/genre"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true" />

    </RelativeLayout>
</androidx.cardview.widget.CardView>

Bước 5: Adapter (src/MoviesAdapter.java)

package app.com.sample;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;

public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {

    private List<MovieModel> moviesList;

    // ViewHolder: nắm giữ reference các View của 1 item
    static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView title, year, genre;
        MyViewHolder(View view) {
            super(view);
            title = view.findViewById(R.id.title);
            genre = view.findViewById(R.id.genre);
            year = view.findViewById(R.id.year);
        }
    }

    public MoviesAdapter(List<MovieModel> moviesList) {
        this.moviesList = moviesList;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.movies_list, parent, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        MovieModel movie = moviesList.get(position);
        holder.title.setText(movie.getTitle());
        holder.genre.setText(movie.getGenre());
        holder.year.setText(movie.getYear());
    }

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

Bước 6: MainActivity (src/MainActivity.java)

package app.com.sample;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<MovieModel> movieList = new ArrayList<>();
    private MoviesAdapter mAdapter;

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

        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        mAdapter = new MoviesAdapter(movieList);

        // LayoutManager: LinearLayoutManager (danh sách dọc), GridLayoutManager (lưới), StaggeredGridLayoutManager
        LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(layoutManager);

        // ItemAnimator: hiệu ứng thêm/xóa item
        recyclerView.setItemAnimator(new DefaultItemAnimator());

        recyclerView.setAdapter(mAdapter);

        // Chuẩn bị dữ liệu mẫu
        prepareMovieData();
    }

    private void prepareMovieData() {
        MovieModel movie = new MovieModel("Mad Max: Fury Road", "Action & Adventure", "2015");
        movieList.add(movie);
        movie = new MovieModel("Inside Out", "Animation, Kids & Family", "2015");
        movieList.add(movie);
        movie = new MovieModel("Star Wars: Episode VII - The Force Awakens", "Action", "2015");
        movieList.add(movie);
        // ... thêm nhiều phim khác ...
        movie = new MovieModel("Guardians of the Galaxy", "Science Fiction & Fantasy", "2014");
        movieList.add(movie);

        // Thông báo adapter dữ liệu đã thay đổi
        mAdapter.notifyDataSetChanged();
    }
}

Bước 7: Manifest (androidManifest.xml)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. Danh sách phim hiển thị trong RecyclerView cuộn mượt mà.

Làm việc với RecyclerView trong ứng dụng Android Làm việc với RecyclerView trong ứng dụng Android

Dependency cần thiết (build.gradle)

dependencies {
    implementation 'androidx.recyclerview:recyclerview:1.3.2'
    implementation 'androidx.cardview:cardview:1.0.0'
}

Khái niệm cốt lõi

Component Vai trò
RecyclerView Container chính, quản lý recycling views
LayoutManager Quy định sắp xếp: Linear (list), Grid, StaggeredGrid
Adapter Cung cấp dữ liệu, tạo ViewHolder, bind data
ViewHolder Cache các View con của item (findViewById 1 lần)
ItemAnimator Animation thêm/xóa/di chuyển item (DefaultItemAnimator)

Mở rộng phổ biến

  • Click listener: Interface callback trong Adapter → MainActivity implement.
  • DiffUtil + ListAdapter: Tối ưu hiệu suất cập nhật danh sách (chỉ reload item thay đổi).
  • Pagination: Load thêm dữ liệu khi cuộn gần cuối (Paging 3 library).
  • Swipe to dismiss / Drag & drop: ItemTouchHelper.
  • Multiple View Types: Override getItemViewType() trong Adapter.