Android:RecyclerView 的使用,有这一篇就够了

2023-11-02

谨以文章记录学习历程,如有错误还请指明。

RecyclerView 简介

首先,可以理解 RecyclerView 是 ListView 的升级版,更加灵活,同时由于封装了 ListView 的部分实现,导致其使用更简单,结构更清晰。

从名字 RecyclerView 来看,它直接提供了回收复用的功能,虽然 ListView 我们也可以自己实现 ViewHolder 以及 convertView 进行优化,但是在 RecyclerView 中,它直接封装了 ViewHolder 的回收复用,也就是说 RecyclerView 将 ViewHolder 标准化,我们不再需要面向 view ,而是直接面向 ViewHolder 编写实现我们需要的 Adapter,这样一来,逻辑结构就变得非常清晰。

当然,说到 RecyclerView 的优点,就不得不提它的 插拔式 的体验,高度解耦:

  • 布局(显示方式):可通过LayoutManager(LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager )设置;
  • 分割线:通过 ItemDecoration 实现
  • Item 增删动画:通过 ItemAnimator
  • ViewHolder 的创建和绑定:通过实现 Adapter

除此之外,还需要额外提一下关于点击事件的问题,RecyclerView 本身是不提供点击、长按事件的,而隔壁的 ListView 稳稳支持。对此,可能刚接触 RecyclerView 的同学会疯狂吐槽,怎么作为升级版的 RecyclerView 在这一点上还不如旧版呢?

情况真的是这样么?

显然不是

ListView 中对于点击事件的处理,其实是有很大弊端的,它的 setOnItemClickListener() 方法是为子项注册点击事件,这就导致只能识别到这一整个子项,对于子项中的组件比如按钮就束手无策了。为此,RecyclerView 直接放弃了这个为子项注册点击事件的监听方法,所有点击事件都有具体 View 去注册,好处显而易见,我可以按需为组件注册点击事件,不存在点击不到的组件。

基础知识补充

如果读者从未接触过 ListView 和 RecyclerView,那么可能对前面提到的 ViewHolder、Adapter等一头雾水,为此在这里补充一些基础知识。

  • LayoutManager:RecyclerView 会根据 Layout Manager 提供的视图来填充自身,常用的布局管理器有LinearLayoutManager(线性布局管理器)、GridLayoutManager(网格布局管理器)、StaggeredGridLayoutManager (瀑布流布局管理器)等。
  • ViewHolder:列表中的视图由 ViewHolder 实例展示。 ViewHolder 用于对控件的实例进行缓存,负责显示子项。例如,如果列表显示了音乐集合,那么每个 ViewHolder 可能代表一个专辑。
  • Adapter:ViewHolder 对象由 Adapter 管理。Adapter 按需创建 ViewHolder,并为其绑定数据。绑定意味着根据 Adapter 中的位置为子视图填充对应的数据。

下面我们就介绍一些关于RecyclerView 的用法。

RecyclerView 用法

基础用法

首先,由于 RecyclerView 属于 v7-支持库,因此我们在使用之前需要先添加依赖:

dependencies {
    implementation 'com.android.support:recyclerview-v7:27.1.1'
}

接下来,RecyclerView 的核心使用流程如下:

mRecyclerView = findView(R.id.id_recycler_view);
//设置布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);
//设置adapter
mRecyclerView.setAdapter(mAdapter)
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(
                getActivity(), DividerItemDecoration.HORIZONTAL_LIST));

可能用惯了 ListView ,第一次接触 RecyclerView 的同学会觉得,ListView 只需要一个 Adapter 就足够了,怎么 RecyclerView 的使用这么繁琐。

其实恰恰正是由于 RecyclerView 的高度解耦,本身只提供基本的回收和复用,而其他特性都允许我们自己定制,因此我们可以通过它来灵活地实现各种 复杂花哨 的效果。可以说,RecyclerView 以增加部分代码的代价来增加其灵活性和扩展性。

下面就来介绍一下 如何通过 RecyclerView 轻松实现一个普通列表:

MainActivity.java

public class MainActivity extends AppCompatActivity {
   

    private RecyclerView mRecyclerView;
    private MyAdapter mMyAdapter;
    private LinearLayoutManager mLayoutManager;
    private List<String> list;

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

        mRecyclerView = findViewById(R.id.recycler_view);
        mMyAdapter = new MyAdapter(list);
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mMyAdapter);
    }

    private void initData() {
        list = new ArrayList<>();
        for (int i = 0; i <= 20; i++) {
            list.add("Item " + i);
        }
    }
}

MyAdapter.java

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

    //数据源
    private List<String> mList;

    public MyAdapter(List<String> list) {
        mList = list;
    }

    //返回item个数
    @Override
    public int getItemCount() {
        return mList.size() ;
    }

    //创建ViewHolder
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new NormalHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
    }

    //填充视图
    @Override
    public void onBindViewHolder(@NonNull final MyAdapter.ViewHolder holder, final int position) {
        holder.mView.setText(mList.get(position));
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
   
        public TextView mView;

        public ViewHolder(View itemView) {
            super(itemView);
            mView = itemView.findViewById(R.id.text_view);
        }
    }
}

MainActivity 的布局文件,activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:divider="#FFFF0000"
        android:dividerHeight="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout >

子项布局,Item.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:gravity="center"
        android:background="#c0c7c759"
        android:textSize="20sp"
        android:text="1" />
</FrameLayout>

通过上述代码,就轻轻松松实现了一个列表,效果如下:

这里写图片描述

可以看到,RecyclerView 的实现结构很清晰,且内部直接封装了 ViewHolder,使得我们不再需要像 ListView 一样自己实现 ViewHolder+convertView 去优化,我们只需要面向 ViewHolder 变成即可,关于复用优化的部分 RecyclerView 已经帮我们做好了。

分割线 - ItemDecoration

虽然上面我们实现了一个 列表界面,但是!!这实在是丑的没法看了,我们随便拉出来一个手机里的app,里面的列表颜值都秒杀它,拿微信界面为例:

这里写图片描述

很明显,不同模块间有明显的分割空白,而相同模块不同功能也会有一个分割线,整体看起来结构很清晰。

为了给我们的列表添加分割线的效果,我们就需要了解一下 `RecyclerView.addItemDecoration() 方法,该方法接收一个RecyclerView.ItemDecoration 类型参数,其本身是一个抽象类,这就表明我们可以通过继承这个类,编码实现我们所需要的 复杂花哨 的分割线效果。

下面,我们先来了解一下 ItemDecoration 这个类,源码如下:

public abstract static class ItemDecoration {
   
        //使用此方法绘制的任何内容都将在绘制子项视图之前绘制,从而出现在视图之下。
        public void onDraw(Canvas c, RecyclerView parent, State state) {
            onDraw(c, parent);
        }

        @Deprecated
        public void onDraw(Canvas c, RecyclerView parent) {
        }

        //使用此方法绘制的任何内容都将在绘制子项视图之后绘制,从而出现在视图之上。
        public void onDrawOver(Canvas c, RecyclerView parent, State state) {
            onDrawOver(c, parent);
        }

        @Deprecated
        public void onDrawOver(Canvas c, RecyclerView parent) {
        }

        @Deprecated
        public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
            outRect.set(0, 0, 0, 0);
        }

        //为每个Item设置一定的偏移量
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
            getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
                    parent);
        }
    }

可以看到,这个类实际上是很简单的,可供使用的只有三个方法,而其中 onDraw() 方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:RecyclerView 的使用,有这一篇就够了 的相关文章

  • Android EditText 和 addTextChangedListener

    我目前正在将数据库管理器移植到 Android 由于性能原因 我喜欢 仅更新已修改的属性 我尝试使用 addTextChangedListener 执行此操作 以便将修改后的条目添加到列表中 但我的程序从未输入其任何方法 EditText
  • 用于 Kotlin 中单元测试的 BuildConfigField 模拟

    我正在尝试尽可能多地涵盖Kotlin Android 库我遇到了有关自定义 BuildConfig 变量的问题 更广为人知的是buildConfigField 我想模拟这个变量来测试两者true and false values 从 Gra
  • Android ToggleButton 始终检查

    如果切换按钮处于选中或取消选中状态 我想存储在 SharedPreferences 中 toggle setOnCheckedChangeListener new OnCheckedChangeListener public void on
  • 音频流的最佳实践

    我正在编写一个应用程序来播放远程服务器的音频 我尝试了多种方法来实现流音频 但它们对我来说都不够好 这就是我尝试过的 幼稚地使用 MediaPlayer 就像是 MediaPlayer player new MediaPlayer play
  • 我无法再在后台应用程序中接收任何 FCM 消息

    当应用程序处于后台时 我无法再在应用程序中接收任何数据消息 请注意 直到最近它在我的应用程序中都运行良好 也许在我的开发环境最近更新后它停止工作了 我不能说 所以我尝试用快速入门 android 项目 https github com fi
  • 写入 Android UI Automator 输出控制台

    我正在 Android UI Automator 上编写一个小包装器 通常我们可以在控制台看到测试用例的状态 我可以访问它并添加我自己的消息吗 我努力了System out println 但这没有用 有什么办法可以做到这一点吗 您可以使用
  • VOIP通话录音

    我正在开发一个在 android 中录制 VOIP 通话的项目 我没有找到任何解决方案 有很多应用程序支持手机上的 VOIP 录音 我找不到任何教程和帮助 立方体通话记录器 https play google com store apps
  • Play 商店中的应用描述更新

    我想更新应用程序的描述以及 Play 商店上的屏幕截图 但应用程序保持相同 即相同的版本号 我不想发布新应用程序 因为应用程序中没有任何更改 这可能吗 谷歌也会要求更新应用程序吗 您可以更新描述 也可以更改屏幕截图 您的应用程序将保持不变
  • 自动删除 Firebase 通知

    我有一个问题 我都读过让通知在 5 分钟后消失 https stackoverflow com questions 15648699 make notification disappear after 5 minutes and 几秒钟后清
  • Android:WebView/BaseInputConnection 中的退格键

    我在 Android 4 2 中遇到软键盘退格问题 我在 WebView CodeMirror 中有一个自定义编辑器 它使用一个空的
  • 如何在同一设备上运行的 Android 应用程序之间传输文件?

    我正在编写一个与 RESTful 服务交互的 Android 应用程序 该 Web 服务本质上是一个文件系统 并提供元数据以及对文件的 CRUD 访问 我的应用程序检索元数据 并通过ContentProvider 我需要添加与我的应用程序在
  • Android - 状态栏阻止全屏

    我的应用程序启动时可以全屏正确运行 然而 在最小化然后返回应用程序后 状态栏会弹出 并将我的视图向下推一点 如何防止状态栏移动我的视图 这是我的布局
  • Android 操作项上的通知徽章

    我想在操作栏中放置的购物车图像上添加一个通知徽章 并以编程方式操作它 有帮助吗 您可以显示自定义MenuItem on ActionBar通过创建一个custom layout for MenuItem 要设置自定义布局 您必须使用菜单项属
  • Android 中 Activity 之间的 3D 动画

    How to create animation between two Activity look like As Screen shot in android 搜索jazzyviewpager 这是link https github co
  • 用于请求带有临时缓存的远程 Observable 的 RxJava 模式

    用例是这样的 我想暂时缓存最新发出的昂贵的Observable响应 但在它过期后 返回到昂贵的源Observable并再次缓存它 等等 一个非常基本的网络缓存场景 但我真的很难让它工作 private Observable
  • 调试android数据绑定?

    谁能告诉我如何调试或找到数据绑定生成的代码 从this https www youtube com watch v NBbeQMOcnZ0链接我发现它生成了所需的代码 我猜您正在寻找自动生成的绑定 java 文件 我也在寻找他们 最后我在这
  • 动态更改按钮上的图像视图

    在我的应用程序中 我有按钮和ImageView 当我按下按钮时我想改变ImageView 我的可绘制文件夹中有 5 张图像 按下按钮时 ImageView 根据按钮单击一张一张地更改图像 我想要它的解决方案 感谢任何可以提供帮助的人 维护一
  • 在数组列表中过滤 Filterable 不取消之前的过滤

    我看过过滤器方法文档 其中显示调用过滤器会取消所有先前未执行的过滤请求 并发布一个稍后将执行的新过滤请求 但我收到的实际回调有些不同 在我的实现中 它不会取消先前的过滤器请求并调用publishResults 最近一次搜索条件后的上一次搜索
  • 我想测量 ListView 的高度 (getHight() = 0)

    我无法自己决定任务将是问 我想测量 ListView 的高度 无法捕捉渲染 ListView 的时刻 rssListView getHight 0 public class RSSactivity extends Activity publ
  • 如何用LoaderManager自动重新查询

    我有一个应用程序显示来自 SQLite DB 的数据 并且数据不断变化 所以显然 我认为我应该使用 LoaderManager 来显示数据 我读过一些关于将 LoaderManager 与 SQLite 结合使用的内容 然后看到了亚历克斯

随机推荐

  • 终于,在Excel里也能直接写python了

    之前在处理数据的时候 最开始都是在excel里处理 后来当数据量上了一个级别后就用python导入excel文件接着处理了 很多人会说 excel有自带VBA语言 可以用那个来处理呀 不好意思 VBA不仅处理数据速度慢而且还非常麻烦 但是
  • 【51单片机实验笔记】前篇(三) 模块功能封装汇总(持续更新)

    文章目录 通用函数 public h public c 延时函数 delay h delay c LED模块 数码管模块 smg h smg c LED点阵模块 独立按键模块 矩阵按键模块 外部中断模块 定时器模块 串口通讯模块 ADC模块
  • 独家

    作者 宋莹 本文长度为10427字 建议阅读20 分钟 本文为你介绍数据挖掘的知识及应用 引言 最近笔者学到了一个新词 叫做 认知折叠 就是将复杂的事物包装成最简单的样子 让大家不用关心里面的细节就能方便使用 作为数据科学领域从业者 我们所
  • Jupyter notebook从电脑本地读取csv文件

    在菜单中打开Anaconda Prompt 然后输入 jupyter notebook generate config 打开输出的路径的配置文件 找到 c NotebookApp notebook dir 然后将 去掉 并且在 中写入想要存
  • Java poi导出word文件

    Java在导出word文件时主要对表格中内容垂直居中处理做以记录方便后续碰到类似问题解决 maven pom xml中添加poi依赖
  • 使用IDEA导入SpringBoot项目

    有时候会拿到别人现成的 springboot 项目 而不是从头自己做一个 这个时候 就需要用导入的方式来 import 这么一个项目了 1 IDEA 导入 SpringBoot 项目办法 1 菜单 gt File gt New gt Pro
  • 2021-05-05 星期三 常用的算法的时间复杂度和空间复杂度

    常用的算法的时间复杂度和空间复杂度
  • 变分推断和指数族分布

    一 变分推断基础 首先 对数先验概率有 ln p X ln p X Z p Z X ln p X Z q Z q Z p Z X ln p X Z q Z ln q Z p Z X 1 2 3 1 l n p
  • JDK 安装 与环境变量配置 详细教程

    1 JDK jre 8u161 windows x64 exe 下载 所有平台 http www oracle com technetwork java javase downloads jdk8 downloads 2133151 htm
  • 微信小程序登录授权

    一般的微信小程序登录都会先前端调用wx login生成code传给后端 后端通过code获取到openid和session key并返回给前端 前端调用wx getUserInfo获取对象参数等信息 由于需求问题 我所写的小程序登录直接由前
  • java中unexpected token

    文章目录 问题 问题 public class People int m 10 n 1 n 200 2 void f if m n n m 3 else n n m 4 这道题问的是 下列哪行代码有错误 一开始并没有发现问题的所在 放了编辑
  • 寻找环形链表的入口点

    如果链表中有某个节点 可以通过连续跟踪 next 指针再次到达 则链表中存在环 为了表示给定链表中的环 我们使用整数来表示链表尾连接到链表中的位置 索引从 0 开始 先定义一个节点 struct ListNode int val struc
  • 通讯协议与即时通讯

    转自 https www jianshu com p ca4aeabf55f6 推送服务一般有三种实现方式 1 轮询方式 客户端不断的查询服务器 检索新内容 这种方式的缺点十分明显 如果轮询频率过快 会大量消耗网络带宽和电池 2 长连接方式
  • FPGA学习---3.IP核使用,Counter IP核

    三 LPM counter IP核使用 小结 counter IP核 cin进位输入 clock时钟信号 cout进位输出 q当前计数值 FPGA设计方式 调用IP核 路径放到prj的ip文件夹下 名字叫counter就行 几位的计数器 计
  • Ubuntu 中vi下方向键变成ABCD, backspace无法删除字符的解决办法

    转载自 https blog csdn net sunzz pku article details 40581881 在linux中安装完VIM后 发现在insert模式下 按下四个方向键在屏幕中会输出ABCD这样的字符 并且Backspa
  • Java学习笔记 --- IDEA

    一 IDEA介绍 1 IDEA全称IntelliJ IDEA 2 在业界被公认为最好的Java开发工具 3 IDEA是JetBrains公司的产品 总部位于捷克的首都布拉格 4 除了支持Java开发 还支持HTML CSS PHP MySQ
  • Sonar 配置代码扫描规则 与 质量配置,设置各个语言默认的扫描规则

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 配置代码扫描规则 质量配置 设置各个语言默认的扫描规则 代码规则设置 如果认为有些扫描规则太严格了 可以把它 挂起 以后再构建的代码扫描项目时就不会再使用本规则 例如挂起J
  • electron-14版后remote废除

    文章目录 前言 安装与配置 前言 Electron最近的版本变迁比较频繁 在升级到14 0 0版本后 废除了很多旧有的API 而其中最主要的就是remote模块从旧有的模块里抽出 变成了一个需要新安装的模块 electronic remot
  • Android升级到7.0使得webview加载页面为空白页

    前段时间 公司一哥们把他的手机拿给我看 问到公司的软件加载进去是空白页 等了好久也是空白 我也为是网络出现了问题 排查没问题啊 看看是不是缓存问题 又是清缓存 又是卸载重装 结果还是空白页面 想了一下是不是系统问题 问他有没有更新过系统 结
  • Android:RecyclerView 的使用,有这一篇就够了

    谨以文章记录学习历程 如有错误还请指明 RecyclerView 简介 首先 可以理解 RecyclerView 是 ListView 的升级版 更加灵活 同时由于封装了 ListView 的部分实现 导致其使用更简单 结构更清晰 从名字