《Android 应用开发基础教程》——第五章:RecyclerView 列表视图与适配器机制

发布于:2025-04-22 ⋅ 阅读:(12) ⋅ 点赞:(0)

目录

第五章:RecyclerView 列表视图与适配器机制

5.1 为什么要使用 RecyclerView?

5.2 基本结构图

5.3 RecyclerView 使用步骤

1️⃣ 添加 RecyclerView 依赖(Android Studio)

2️⃣ 布局文件(activity_main.xml)

3️⃣ 创建单项布局(item_text.xml)

4️⃣ 创建适配器类(MyAdapter.java)

5️⃣ 在 MainActivity 中使用 RecyclerView

5.4 支持点击事件

5.5 设置不同布局方式

网格布局:

瀑布流布局:

5.6 分割线和动画(可选)

添加分割线:

✅ 本章小结

习题答案

项目结构

1. MainActivity.java

2. DetailActivity.java

3. MyAdapter.java

4. ItemModel.java

5. activity_main.xml

6. activity_detail.xml

7. item_layout.xml

 


第五章:RecyclerView 列表视图与适配器机制


5.1 为什么要使用 RecyclerView?

RecyclerView 是 Android 中用于显示长列表或网格数据的强大控件,相比早期的 ListView 有以下优势:

优势 描述
灵活布局 支持线性、网格、瀑布流布局
高性能 内置“复用机制”,提高性能
自定义强 可自定义 ViewHolder、动画、分隔线

5.2 基本结构图

RecyclerView
  ├── Adapter(适配器)
  │     └── ViewHolder(单项视图)
  └── LayoutManager(布局管理器)

5.3 RecyclerView 使用步骤

假设我们要展示一个简单的字符串列表。


1️⃣ 添加 RecyclerView 依赖(Android Studio)
dependencies {
    implementation 'androidx.recyclerview:recyclerview:1.3.1'
}


2️⃣ 布局文件(activity_main.xml)
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>


3️⃣ 创建单项布局(item_text.xml)
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textItem"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:gravity="center_vertical"
    android:padding="16dp"
    android:textSize="18sp"/>

4️⃣ 创建适配器类(MyAdapter.java)
package com.example.myapp;

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

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    private List<String> dataList;

    public MyAdapter(List<String> dataList) {
        this.dataList = dataList;
    }

    // ViewHolder:缓存 item 控件
    static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView textItem;

        MyViewHolder(View itemView) {
            super(itemView);
            textItem = itemView.findViewById(R.id.textItem);
        }
    }

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

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.textItem.setText(dataList.get(position));
    }

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


5️⃣ 在 MainActivity 中使用 RecyclerView
package com.example.myapp;

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

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private MyAdapter adapter;
    private List<String> stringList;

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

        recyclerView = findViewById(R.id.recyclerView);
        stringList = new ArrayList<>();

        // 添加测试数据
        for (int i = 1; i <= 20; i++) {
            stringList.add("第 " + i + " 项");
        }

        adapter = new MyAdapter(stringList);
        recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 垂直列表
        recyclerView.setAdapter(adapter);
    }
}


5.4 支持点击事件

修改 MyAdapter.java 中的 onBindViewHolder 方法:

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    holder.textItem.setText(dataList.get(position));
    
    holder.textItem.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(v.getContext(), "点击了:" + dataList.get(position), Toast.LENGTH_SHORT).show();
        }
    });
}


5.5 设置不同布局方式

网格布局:
recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); // 2 列

瀑布流布局:
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));


5.6 分割线和动画(可选)

添加分割线:
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));


✅ 本章小结

概念 说明
RecyclerView 高效列表展示控件
Adapter 数据适配器,负责绑定数据
ViewHolder 用于提高性能的视图缓存机制
LayoutManager 控制列表排列方式(线性、网格等)

📌 练习题

  1. 修改 Adapter,点击列表项后跳转到新的 Activity 并传递字符串

  2. 使用 GridLayoutManager 显示 3 列网格

  3. 自定义 item 布局,包括头像、标题、内容三部分


下一章预告:

第六章:列表数据动态更新与刷新(如添加、删除、SwipeRefresh)


习题答案

项目结构

MainActivity.java
DetailActivity.java
MyAdapter.java
activity_main.xml
activity_detail.xml
item_layout.xml

1. MainActivity.java

package com.example.demo;

import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

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

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private MyAdapter adapter;
    private List<ItemModel> itemList;

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

        recyclerView = findViewById(R.id.recyclerView);

        // 初始化数据
        itemList = new ArrayList<>();
        itemList.add(new ItemModel("Avatar 1", "Title 1", "Content 1"));
        itemList.add(new ItemModel("Avatar 2", "Title 2", "Content 2"));
        itemList.add(new ItemModel("Avatar 3", "Title 3", "Content 3"));
        itemList.add(new ItemModel("Avatar 4", "Title 4", "Content 4"));
        itemList.add(new ItemModel("Avatar 5", "Title 5", "Content 5"));

        // 设置 Adapter 和 LayoutManager
        adapter = new MyAdapter(itemList, this);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); // 3 列网格布局
        recyclerView.setAdapter(adapter);

        // 设置点击事件监听器
        adapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(String title) {
                Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                intent.putExtra("TITLE", title); // 传递标题
                startActivity(intent);
            }
        });
    }
}

2. DetailActivity.java

package com.example.demo;

import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class DetailActivity extends AppCompatActivity {

    private TextView textViewTitle;

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

        textViewTitle = findViewById(R.id.textViewTitle);

        // 获取传递的标题并显示
        String title = getIntent().getStringExtra("TITLE");
        if (title != null) {
            textViewTitle.setText(title);
        }
    }
}

3. MyAdapter.java

package com.example.demo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private List<ItemModel> itemList;
    private Context context;
    private OnItemClickListener listener;

    public MyAdapter(List<ItemModel> itemList, Context context) {
        this.itemList = itemList;
        this.context = context;
    }

    // 定义点击事件接口
    public interface OnItemClickListener {
        void onItemClick(String title);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        ItemModel item = itemList.get(position);
        holder.textViewTitle.setText(item.getTitle());
        holder.textViewContent.setText(item.getContent());

        // 模拟头像(可以替换为实际图片加载逻辑)
        holder.imageViewAvatar.setImageResource(R.drawable.ic_launcher_foreground);

        // 设置点击事件
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) {
                    listener.onItemClick(item.getTitle());
                }
            }
        });
    }

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

    public static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView imageViewAvatar;
        TextView textViewTitle;
        TextView textViewContent;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            imageViewAvatar = itemView.findViewById(R.id.imageViewAvatar);
            textViewTitle = itemView.findViewById(R.id.textViewTitle);
            textViewContent = itemView.findViewById(R.id.textViewContent);
        }
    }
}

4. ItemModel.java

package com.example.demo;

public class ItemModel {
    private String avatar;
    private String title;
    private String content;

    public ItemModel(String avatar, String title, String content) {
        this.avatar = avatar;
        this.title = title;
        this.content = content;
    }

    public String getAvatar() {
        return avatar;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }
}

5. activity_main.xml

<?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:orientation="vertical">

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

6. activity_detail.xml

<?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:orientation="vertical"
    android:gravity="center"
    android:padding="16dp">

    <TextView
        android:id="@+id/textViewTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"
        android:textSize="24sp" />
</LinearLayout>

7. item_layout.xml

<?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="wrap_content"
    android:orientation="vertical"
    android:padding="8dp"
    android:gravity="center">

    <ImageView
        android:id="@+id/imageViewAvatar"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:src="@drawable/ic_launcher_foreground"
        android:contentDescription="Avatar" />

    <TextView
        android:id="@+id/textViewTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title"
        android:textSize="16sp"
        android:gravity="center"
        android:paddingTop="4dp" />

    <TextView
        android:id="@+id/textViewContent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Content"
        android:textSize="14sp"
        android:gravity="center"
        android:paddingTop="2dp" />
</LinearLayout>


网站公告

今日签到

点亮在社区的每一天
去签到