Android studio 之 ListView

ListView 绑定的适配器是 BaseAdapter。

复制代码
// 获取视图(设置 listView 每一项的显示效果)
    /* 参数1:当前Item的下标 --- 和数据源的下标相同,可以由此获取数据源配置item
     * 参数2:当前Item的view
     * 参数3:当前视图的父视图(可调整当前视图的宽高)*/
    public View getView(int position, View convertView, ViewGroup parent) {
        // 完成对view的设置
        // 将设置好的 item 布局资源转换成view
        convertView = LayoutInflater.from(context).inflate(R.layout.baseadapter_item,null); // 此时得到的是最初的item布局,没有添加的数据

        // 获取数据源[position] 的数据,并将他们设置到item视图中的控件中
        BaseMsg m = baseMsgList.get(position); // 获取item的数据列表

        ImageView imageView = convertView.findViewById(R.id.base_icon);
        imageView.setImageResource(m.getIcon());

        TextView tN = convertView.findViewById(R.id.base_name);
        tN.setText(m.getNickName());

        TextView tC = convertView.findViewById(R.id.base_content);
        tC.setText(m.getContent());

        // 可以给item的单个控件设置点击事件
        tN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              //  System.out.printf("点击了"+tN.getText());
                Toast.makeText(context,"你点击了"+m.getNickName(),Toast.LENGTH_SHORT).show();
            }
        });
        return convertView;
    }

问题一:优化view对象

在MyAdapter类中的getView方法中,我们注意到,上面的写法在每个视图出现时都会执行,有多少个item就会调用多少次 getView() 如果item太多就会很浪费资源!!

优化:可以复用convertView

  • 在 getView 方法中,首先检查 convertView 是否为空。

  • 如果为空,表示当前屏幕上没有可复用的 item 视图,需要创建新的视图并进行布局设置。

  • 但是,如果 convertView 不为空,就意味着该视图已经被创建过,并且已经在屏幕上显示过,这时我们可以直接复用 convertView,避免了重复的布局加载和赋值操作

    public View getView(int position, View convertView, ViewGroup parent) {

    复制代码
          // 优化1:利用进入 RecyclerBin 中的view,减少对view的赋值
          /* 当视图第一次构建后,上下滑动到看不见时就会进入 RecyclerBin,此时 convertView 就不为null,
           * 我们就可以复用这个 convertView */
          if( convertView == null){
              // 完成对view的设置
              // 将设置好的 item 布局资源转换成view
              convertView = LayoutInflater.from(context).inflate(R.layout.baseadapter_item,null); // 此时得到的是最初的item布局,没有添加的数据
              System.out.println("当前显示的视图"+(position+1));
          }
          // 获取数据源[position] 的数据,并将他们设置到item视图中的控件中
          BaseMsg m = baseMsgList.get(position); // 获取item的数据列表
    
          ImageView imageView = convertView.findViewById(R.id.base_icon);
          imageView.setImageResource(m.getIcon());
    
          TextView tN = convertView.findViewById(R.id.base_name);
          tN.setText(m.getNickName());
    
          TextView tC = convertView.findViewById(R.id.base_content);
          tC.setText(m.getContent());
    
          // 可以给item的单个控件设置点击事件
          tN.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                //  System.out.printf("点击了"+tN.getText());
                  Toast.makeText(context,"你点击了"+m.getNickName(),Toast.LENGTH_SHORT).show();
              }
          });
          return convertView;
      }

问题二:优化view中组件的查找

即使经过优化1的步骤,可以减少view的构建,但是每出现一个view已经会寻找一次控件id,findViewById 依旧十分浪费资源,因此可以进行第二步优化

优化:利用viewHolder

在convertView为null的时候,我们不仅重新inflate出来一个view,并且还需要进行findviewbyId的查找工作,但是同时我们还需要获取一个ViewHolder类的对象,并将findviewById的结果赋值给ViewHolder中对应的成员变量。最后将holder对象与该view对象"绑"在一块--setTag方法

当convertView不为null时,我们让view=converView,同时取出这个view对应的holder对象--getTag方法,就获得了这个view对象中的TextView组件,

复制代码
// 即使经过优化1的步骤,可以减少view的构建,但是每出现一个view已经会寻找一次控件id,findViewById 依旧十分浪费资源,因此可以进行第二步优化
// 1.定义一个 内部类 ViewHolder,并声明需要用到的控件属性
// 2.当 convertView == null 当前视图没有被创建时,初始化一个 ViewHolder 对象,并为其中的控件赋值
// 3.调用 contvertView.setTag(ViewHolder) 将这个 HolderView 绑定到这个view中
// 4.当 convertView != null时,通过 contvertView.getTag() 找到绑定的ViewHolder
       
ViewHolder holder;
if (convertView == null) {
  // 完成对view的设置
  // 将设置好的 item 布局资源转换成view
  convertView = LayoutInflater.from(context).inflate(R.layout.baseadapter_item, null); // 此时得到的是最初的item布局,没有添加的数据

   holder = new ViewHolder();
   holder.icon = convertView.findViewById(R.id.base_icon);
   holder.nickName = convertView.findViewById(R.id.base_name);
   holder.content = convertView.findViewById(R.id.base_content);
   convertView.setTag(holder);
   System.out.println("当前显示的视图" + (position + 1));
} else {
   holder = (ViewHolder) convertView.getTag(); // 取出view中绑定的ViewHolder,此时要强转成 ViewHolder 类型
 }

 public View getView(int position, View convertView, ViewGroup parent) {

        // 优化1:利用进入 RecyclerBin 中的view,减少对view的赋值
        /* 当视图第一次构建后,上下滑动到看不见时就会进入 RecyclerBin,此时 convertView 就不为null,
         * 我们就可以复用这个 convertView */

        // 即使经过优化1的步骤,可以减少view的构建,但是每出现一个view已经会寻找一次控件id,findViewById 依旧十分浪费资源,因此可以进行第二步优化
        // 1.定义一个 内部类 ViewHolder,并声明需要用到的控件属性
        // 2.当 convertView == null 当前视图没有被创建时,初始化一个 ViewHolder 对象,并为其中的控件赋值
        // 3.调用 contvertView.setTag(ViewHolder) 将这个 HolderView 保存到这个view中
        // 4.当 convertView != null时,通过 contvertView.getTag() 找到保存的ViewHolder
        ViewHolder holder;
        if (convertView == null) {
            // 完成对view的设置
            // 将设置好的 item 布局资源转换成view
            convertView = LayoutInflater.from(context).inflate(R.layout.baseadapter_item, null); // 此时得到的是最初的item布局,没有添加的数据

            holder = new ViewHolder();
            holder.icon = convertView.findViewById(R.id.base_icon);
            holder.nickName = convertView.findViewById(R.id.base_name);
            holder.content = convertView.findViewById(R.id.base_content);
            convertView.setTag(holder);

            System.out.println("当前显示的视图" + (position + 1));
        } else {
            holder = (ViewHolder) convertView.getTag(); // 此时要强转成 ViewHolder 类型
        }
        // 获取数据源[position] 的数据,并将他们设置到item视图中的控件中
        BaseMsg m = baseMsgList.get(position); // 获取item的数据列表

        /*ImageView imageView = convertView.findViewById(R.id.base_icon);
        imageView.setImageResource(m.getIcon());*/
        holder.icon.setImageResource(m.getIcon());

        /*TextView tN = convertView.findViewById(R.id.base_name);
        tN.setText(m.getNickName());*/
        holder.nickName.setText(m.getNickName());

        /*TextView tC = convertView.findViewById(R.id.base_content);
        tC.setText(m.getContent());*/
        holder.content.setText(m.getContent());

        // 可以给item的单个控件设置点击事件
        holder.nickName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, "你点击了" + m.getNickName(), Toast.LENGTH_SHORT).show();
            }
        });
        return convertView;
    }
相关推荐
Java致死1 小时前
设计模式Java
java·开发语言·设计模式
源码方舟1 小时前
SpringBoot + Shiro + JWT 实现认证与授权完整方案实现
java·spring boot·后端
奔跑吧 android1 小时前
【android bluetooth 框架分析 02】【Module详解 6】【StorageModule 模块介绍】
android·bluetooth·bt·aosp13·storagemodule
2401_cf4 小时前
为什么hadoop不用Java的序列化?
java·hadoop·eclipse
帮帮志4 小时前
idea整合maven环境配置
java·maven·intellij-idea
LuckyTHP4 小时前
java 使用zxing生成条形码(可自定义文字位置、边框样式)
java·开发语言·python
田一一一5 小时前
Android framework 中间件开发(三)
android·中间件·framework·jni
无声旅者7 小时前
深度解析 IDEA 集成 Continue 插件:提升开发效率的全流程指南
java·ide·ai·intellij-idea·ai编程·continue·openapi
Ryan-Joee8 小时前
Spring Boot三层架构设计模式
java·spring boot
Hygge-star8 小时前
【数据结构】二分查找5.12
java·数据结构·程序人生·算法·学习方法