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)
  • 基础内容

  • AndroidCore

  • Android UI

  • Components

    • ListView

      • 认识ListView
      • Adapter
      • ViewHolder
        • 什么是ViewHolder
        • ViewHolder优化
          • setTag作行李
        • ListView优化
      • 自定义Adapter
      • ListView的点击事件
    • RecyclerView

    • ViewPager

    • TabLayout

  • Fragment

  • 网络操作

  • 异步机制

  • 数据存储

  • 学习笔记

  • 自定义View

  • View事件体系

  • Android
  • Components
  • ListView
iqqcode
2021-06-17
目录

ViewHolder

# 什么是ViewHolder

要想使用 ListView 就需要编写一个 Adapter 将数据适配到 ListView上,而为了节省资源提高运行效率,一般自定义类 ViewHolder 来减少 findViewById() 的使用以及避免过多地 inflate view,从而实现目标。

  • findViewById()通过将结果缓存在Holder对象中,它可以帮助您最大程度地减少调用次数。
  • 如果使用ListViews和RecyclerViews,所有视图都使用一个布局文件,则findViewById()一次又一次地访问可能很耗时。
  • ViewHolder 可以通过为每个listItem提供一个标记来减少这种情况,这样您就可以立即访问它们,而无需重复查找它们。

# ViewHolder优化

将findViewById()反射出来的控件对象进行存储

ViewHolde类:存储需要赋值的控件(可定义为Adapter内部类)

public class ViewHolder {
    ImageView logo;
    TextView app_name;
    TextView app_version;
    TextView app_package;
}
1
2
3
4
5
6

ViewHolder的使用

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // [二级优化] ViewHolder
        ViewHolder holder = null;

        // [一级优化] convertView减少inflate的次数
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item_view, null);

            // 获取控件
            holder = new ViewHolder();
            holder.logo = convertView.findViewById(R.id.logo); // ImageView
            holder.app_name = convertView.findViewById(R.id.app_name); // TextView
            //
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.logo.setImageResource((Integer) list.get(position).get("logo"));
        holder.app_name.setText((String) list.get(position).get("title"));

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

ViewHolder原理

将ViewHolder作为整体放入缓存池,类中包含的是findViewById反射出来的控件对象;

image-20210316160751099

item7 在复用 item1 时,还携带了 item1 反射好的控件对象(除了当前的布局视图view对象之外,还包含ImageView和TextView控件对象),大大减少了反射执行的操作次数

# setTag作行李

setTag()并不是专门针对ListView优化的方法,可以让当前对象携带任何其他类型的对象(Object)

  • 将findViewById查找出来的控件捆绑到一起放到ViewHolder上,将ViewHolder作为一个 行李 让 ConvertView 来携带;因为convertView对象不进入到缓存池,当下一个 item 复用时再将ViewHolder行李交给新的 item

去教室上课时要背书包,上完课后回来将书包放下



# ListView优化

img

Adapter Demo

/**
 * @Author: iqqcode
 * @Date: 2021-04-30 21:53
 * @Description: ListView-Adapter的优化
 */
public class MyBaseAdapter extends BaseAdapter {

    private List<AppInfo> list; // 乘方数据源的容器

    // 反射器: 将item的XML布局文件反射成为View
    private LayoutInflater inflater;

    public MyBaseAdapter(Context context, List<AppInfo> list) {
        // 初始化上下文
        this.inflater = LayoutInflater.from(context);
        this.list  = list;
    }


    @Override
    public int getCount() {
        return list == null ? 0 : list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // [二级优化] ViewHolder
        ViewHolder holder = null;

        // [一级优化] convertView减少inflate的次数
        if (convertView == null) {

            Log.e("TAG", "getView() *** position = " + position + " convertView = " + convertView);

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

            convertView = inflater.inflate(R.layout.item_view, null);

            // 2. 获取控件
            holder = new ViewHolder();
            holder.logo = convertView.findViewById(R.id.item_image);
            holder.app_name = convertView.findViewById(R.id.item_text_app_name);
            holder.app_size = convertView.findViewById(R.id.item_text_app_size);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        // 每个item加载的内容是不同的,所以需要重复获取(无法优化)

        AppInfo info = new AppInfo();
        holder.logo.setImageResource(list.get(position).getAppIcon());
        holder.app_name.setText(list.get(position).getAppName());
        holder.app_size.setText(list.get(position).getAppSize());

        // 返回实实在在的view供系统渲染item
        return convertView;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
编辑 (opens new window)
上次更新: 2022/03/27, 22:58:50
Adapter
自定义Adapter

← Adapter 自定义Adapter→

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