icode icode
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

iqqcode

保持对技术的探索实践与热爱
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • ListView

    • 适配器模式
    • 认识ListView
    • Adapter
    • ViewHolder
    • 自定义Adapter
      • 1. 自定义Adapter
        • 自定义Adapter工作原理
        • LayoutInflater
      • 2. 存在的问题
        • 解决
      • 3. item复用
        • 小结
      • 4. 事件的消化
    • ListView的点击事件
  • RecyclerView

  • ViewPager

  • Component
  • ListView
iqqcode
2021-06-02
目录

自定义Adapter

# 1. 自定义Adapter

名称 说明
ArrayAdapter 适用于简单的文字列表
SimpleAdapter 简单的图文列表,不适用复杂的业务
自定义Adapter 自定义的灵活的适配器

实现自定义Adapter的步骤:

  1. 继承 BaseAdapter
  2. 实现getView()
  3. 关联ListView

# 自定义Adapter工作原理

image-20210316125653209

需要使用 Adapter 将 集合数据 和每一个 item所对应的布局 动态适配至ListView中显示

item布局文件需要通过LayoutInflater将XML布局文件转换为 View对象,从而设置控件的内容

Adapter作为组装者,将 Data 和 item的layout 在**getView** 中进行组合,每一个position就是当前 getView方法组装并且绘制出的内容,显示在ListView(ViewGroup)上

# LayoutInflater

反射器: 将item的XML布局文件 反射 成为View对象到内存中

LayoutInflater反射出行布局对象,并填充上数据内容;拿到view视图对象,从item布局文件反射器获取而来(XML文件映射成为内存中实际存在的View对象)

LayoutInflater inflater;

// 父容器对象不需要传递,因为仅仅是展示
View view = inflater.inflate(R.layout.item_view, null); 
1
2
3
4

# 2. 存在的问题

在每次调用getView方法中都要执行2个耗时操作(反射为耗时操作)

  • inflate方法(获取布局对象)
  • findViewById方法(获取控件对象)

# 解决

在getView方法中使用 convertView 和 ViewHolder

  • inflate方法耗时:convertView解决 (一级优化)
  • findViewByld方法耗时:ViewHolder解决 (二级优化)

其实就是在优化反射操作,尽可能的做到复用,避免低效的重复加载工作


# 3. item复用

item复用:ConvertVie 减少inflate的次数

在getView()中判断是否已存在视图对象

	@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // [一级优化] convertView减少inflate的次数
        if (convertView == null) {
            Log.e("TAG", "getView() *** position = " + position + " convertView = " + convertView);
            // 此处传递this是Adapter的对象
            convertView = inflater.inflate(R.layout.item_view, null);
        }

        // 反射器: 将item的XML布局文件反射成为View
        // 1. 拿到view视图对象,从item布局文件反射器获取而来(XML文件映射成为内存中实际存在的View对象)
        // 父容器对象不需要传递,因为仅仅是展示
        //View view = inflater.inflate(R.layout.item_view, null);

        // 2. 获取控件
        ImageView logo = convertView.findViewById(R.id.logo);

        // 返回实实在在的view供系统渲染item
        return convertView;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

image-20210316145600057

当视图第一次啊加载时:前4个item都是通过inflate放射而来,加载XML中每个item的视图

当item1 和 item2已经滑出屏幕时:

原理上item1 和 item2 对象应该被GC;但是为了循环复用提高效率,将item1 和 item2 对象放入到 Recycle回收池 中,然后给将要加载的 item7和item8来复用

image-20210316150602858

item6 需要通过inflate来反射,但是item7复用item1,item1对象的地址赋给item7;后面的 item均是循环复用

Recycle缓存屏幕显示的 n + 1 个 item,1 是处理半个 item的情况


# 小结

Android渲染ListView遵循以下原则:

  • 无论总量多少,Android只渲染当前屏的item项
  • 被渲染过的item项,它的视图对象会被保存到Recycler中
  • 新滑入屏幕的item项将从Recycler中直接获取缓存的视图,而不是再通过inflate方法反射获取

结论:

  • 无论总量多少,Recylcler中只需要缓存N+1个视图对象,即可保证整个ListView的显示(N为一屏可显示的item数)
  • 无论总量多少,inflate方法最多调用N+1次

# 4. 事件的消化

名称 说明
true 表示消化事件,事件不会继续传递
false 表示不消化事件,事件会继续传递下去

如果希望长按事件后,不再触发点击事件,则应将返回值置位true

表示在点击了长按或者点击时,长按响应了之后就消化了该点击事件,onItemClick不再响应回调

	// 点击事件
	@Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Toast.makeText(this, "点击item" + position, Toast.LENGTH_SHORT).show();
    }  

	// 长按点击 
	@Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        Toast.makeText(this, "长按item" + position, Toast.LENGTH_SHORT).show();
        return true; // false
    }
1
2
3
4
5
6
7
8
9
10
11
12
编辑 (opens new window)
上次更新: 2021/06/02, 10:01:48
ViewHolder
ListView的点击事件

← ViewHolder ListView的点击事件→

最近更新
01
匿名内部类
10-08
02
函数式接口
10-08
03
ARouter-Kotlin踩坑
10-05
更多文章>
Theme by Vdoing | Copyright © 2021-2023 iqqcode | MIT License | 备案号-京ICP备2021028793号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×