ListView的性能优化之convertView和viewHolder

2023-11-03

在这里插入图片描述

ListView优化大致从以下几个角度:
1.复用已经生成的convertView;
2.添加viewHolder类;
3.缓存数据(图片缓存);
4.分页加载。

一、复用convertView
首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。

这连个超链接需要看看 ,写的比较好
http://www.cnblogs.com/itstudent/p/3729117.html
http://blog.csdn.net/jacman/article/details/7087995

这是我做的程序测试:
这里写图片描述

看代码:

package com.example.mypic;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

public class MainActivity extends Activity {
	private ListView listView;
	private MyAdapter adapter;
	private int[] items = new int[] { R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
			R.drawable.pc, R.drawable.pc };
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		listView = (ListView) findViewById(R.id.listView);
		Log.v("aa", "--显示图片-1-");
		adapter = new MyAdapter(this, items);
		Log.v("aa", "--显示图片-2-");
		listView.setAdapter(adapter);
		Log.v("aa", "--显示图片-3-");
		adapter.notifyDataSetChanged();
	}
}
package com.example.mypic;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {
	private int[] items = new int[] {};
	private Context context;
	private String TAG = "aa";
	private Bitmap bitmap = null;

	public MyAdapter(Context context, int[] items) {
		this.context = context;
		this.items = items;
	}

	@Override
	public int getCount() {
		return items.length;
	}

	@Override
	public Object getItem(int position) {
		return items[position];
	}

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

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		
		//Log.v(TAG, "position=="+position);
		//Log.v(TAG, "convertView=="+convertView);
		//Log.v(TAG, "ViewGroup=="+parent);
		
		ViewHolder holder;
		if (convertView == null) {
			convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null);
			holder = new ViewHolder();
			holder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
			holder.textView = (TextView) convertView.findViewById(R.id.textView);
			
			Log.v(TAG, position+"----"+holder);
			
			convertView.setTag(holder);
		}else {
			holder = (ViewHolder) convertView.getTag();
			
			Log.v(TAG, position+"--1--"+holder);
		}
		
		bitmap = BitmapCompressTools.decodeSampledBitmapFromResource(
					context.getResources(), R.drawable.pc, 100, 100);
			
		//Log.d(TAG, "压缩之后的图片大小为:" + bitmap.getByteCount());
		holder.imageView.setImageBitmap(bitmap);
		holder.textView.setText("图片"+position);
		
		return convertView;
	}

	class ViewHolder {
		ImageView imageView;
		TextView textView;
	}
}
package com.example.mypic;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class BitmapCompressTools {
	public static Bitmap decodeSampledBitmapFromResource(Resources res,
			int resId, int reqWidth, int reqHeight) {

		// 给定的BitmapFactory设置解码的参数
		final BitmapFactory.Options options = new BitmapFactory.Options();
		// 从解码器中获取原始图片的宽高,这样避免了直接申请内存空间
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(res, resId, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, reqWidth,
				reqHeight);

		// 压缩完后便可以将inJustDecodeBounds设置为false了。
		options.inJustDecodeBounds = false;
		return BitmapFactory.decodeResource(res, resId, options);
	}

	/**
	 * 指定图片的缩放比例
	 * 
	 * @param options
	 * @param reqWidth
	 * @param reqHeight
	 * @return
	 */

	public static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight) {
		// 原始图片的宽、高
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

//		if (height > reqHeight || width > reqWidth) {
//			//这里有两种压缩方式,可供选择。
//			/**
//			 * 压缩方式二
//			 */
//			// final int halfHeight = height / 2;
//			// final int halfWidth = width / 2;
//			// while ((halfHeight / inSampleSize) > reqHeight
//			// && (halfWidth / inSampleSize) > reqWidth) {
//			// inSampleSize *= 2;
//			// }
//			
			/**
			 * 压缩方式一
			 */
			// 计算压缩的比例:分为宽高比例
			final int heightRatio = Math.round((float) height
					/ (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);
			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
//		}

		return inSampleSize;
	}
}

main.ml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" >
    </ListView>

</RelativeLayout>

list_item.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="horizontal" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="20dp"/>

</LinearLayout>

这是运行结果图:
这里写图片描述

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

ListView的性能优化之convertView和viewHolder 的相关文章

  • c# listview取消选择项目

    我正在开发一个 Windows 应用程序 它有一个包含一堆项目的 ListView 当用户单击某个项目时 应用程序会显示该项目的详细信息 这 然后用户就有机会编辑这些详细信息 用户应该单击 每次更改后都会单击 保存 按钮 但当然这种情况并不
  • 为什么 ListView.getCheckedItemPositions() 没有返回正确的值?

    该应用程序有一个ListView启用多项选择后 它在 UI 中按预期工作 但是当我使用以下代码读取值时 Log i TAG Entered SearchActivity saveCategoryChoice SparseBooleanArr
  • 如何在 Xamarin Forms 中的其他项目之上显示 ListView?

    I have a ListView that displays recent Search items I have added it in the Stack Layout of my Main page I want to show L
  • 如何在 React Native ListView 中将项目居中?

    我试图在选择一个项目时将其置于水平列表视图的中心 我当前的策略是首先测量项目并滚动到视图中引用项目的 x 坐标 目前 每当我按下某个项目时ListView滚动到最后x 538 有没有更简单的方法来实现这一点 同时保持代码无状态 功能 con
  • Android上字符串类型listview实现searchview

    我有一个清单items我想在此基础上开始不同的活动item 当我单击它时 它会打开正确的活动 但是当我尝试从搜索视图栏中搜索列表项时 它会打开错误的活动 listView ListView findViewById R id listVie
  • 如何隐藏 WPF ListView 的标头?

    我希望能够隐藏 WPF ListView 中每个网格列顶部的标题 这是我的 ListView 的 XAML
  • 如何在小部件中使用列表视图? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试创建一个从 rss feed 加载到小部件中的列表视图 有谁知道如何在小部件中使用列表视图的教
  • 自定义列表视图的选择器“更改 ListView 背景 - 奇怪的行为”

    我正在用这个教程 http www androidpeople com android custom listview tutorial example part 2 我想为此列表视图添加选择器 我尝试了一些代码 但它不起作用 我该怎么做
  • 如何从复选框数组中保存布尔状态并在使用 SharedPreferences 加载适配器时加载其状态

    我有一个用于列表视图的 CustomAdapter 我需要使用 SharedPreferences 保存布尔数组中的所有复选框状态 我想将技巧的名称 字符串数组 保存为键和每个技巧的状态 我想到的 SharedPreferences 示例
  • 将列表视图项转换为单个位图图像

    参考这个主题 Android 获取所有 ListView 项目的屏幕截图 https stackoverflow com questions 12742343 android get screenshot of all listview i
  • 在flutter中动态显示数据表布局中的JSON数据

    我正在 flutter 中创建动态数据表视图 其中列标题和行值是动态添加的 数据是一个 Json 响应 标题是一个字符串数组 行中要显示的数据也是一个字符串数组 目标是在表视图中显示数据 而不需要任何硬编码值 这就是我尝试显示数据的方法 r
  • ASP.NET 列表视图->单击行->执行操作

    我需要以下方面的帮助 我有一个用隐藏代码填充的列表视图 Linq gt Sql ListView1 DataSource from x in database ITEMS select x ListView1 DataBind 项目内容 I
  • Android中如何制作传统蒙古文ListView

    如何在 Android 应用程序中为垂直蒙古文制作水平滚动的 ListView 背景 Android 对世界上许多语言都有相当好的支持 甚至是阿拉伯语和希伯来语等 RTL 语言 但是 没有内置对自上而下语言的支持 例如传统蒙古语 http
  • jQuery Mobile:Listview 筛选搜索回调函数

    嘿 我想要一个过滤器搜索 这样您输入搜索的两个字母 相应的结果就会显示在列表视图中 我无法像 jqm listview 那样加载整个列表 因为它太大了 有人可以告诉我如何做到这一点 这有点超出了我理解 API 的范围 我知道如何使用 jqu
  • 我可以在 Android 上使用带有文本视图的列表视图和图像图标吗

    我需要一个像下面的 Android 应用程序那样的列表视图 由于我无法发布图片 所以应该是这样的 图片在这里 一些自由文本 用户名等 这是你的任务 任务1 gt 任务2 gt 任务 1 和任务 2 是将从数据库动态获取的列表 我试图拥有一个
  • 动态改变ListView中TextView字体颜色

    我正在将 XML 文档绑定到自定义适配器 列表中的所有项目最初的字体颜色均为白色 XML 文档中的一个节点有一个我正在检查的属性 如果设置了该属性 我想将 ListView 中该项目的字体颜色更改为较深的颜色 我的代码似乎最初可以工作 但是
  • ListView 中的焦点控件

    上下文 我想要一个不会获得焦点的 ListView 例如不会 当用户触摸它时突出显示该行 然而每个行小部件都有它自己的 OnClickListener 这是我在布局 xml 中指定的内容 android choiceMode none an
  • 停止在列表视图中滚动

    我的活动中有一个列表视图和一个图像按钮 当我单击图像按钮时 我想转到列表中的特定位置 我通过调用列表上的 setSelection intposition 来实现此目的 当用户滑动列表视图然后单击图像按钮时会出现问题 列表将转到指定位置但继
  • ListViewItem 与 CheckBox IsChecked 绑定到 ViewModel

    我有一个带有 DataTemplate 的 ListView 用于为每个 ListViewItem 显示一个复选框
  • 如何在 Flutter 中更新 AnimatedList 中的数据

    如何在 Flutter 中更新 AnimatedList 中的数据 添加 删除行 我可以在 ListView 中通过更新支持数据并调用来完成此操作setState 例如 setState data insert 2 pig 不过 在 Ani

随机推荐

  • 模拟实现atoi函数(将数字字符串转换为整型)附加leetcode练习题

    各位朋友们 大家好啊 今天我为大家分享的知识是如何模拟实现atoi函数 相信大家如果能够理解这个知识 对大家以后的刷题是有帮助的 文章目录 什么是atoi函数 atoi函数的作用 先直接使用库函数看看这个函数是什么作用 都是正整数字符的字符
  • [Python知识图谱] 三.Jieba工具中文分词、添加自定义词典及词性标注详解

    本系列文章主要结合Python语言实现知识图谱构建相关工程 具有一定创新性和实用性 非常希望各位博友交流讨论 相互促进成长 前面两篇文章详细讲解了哈工大Pyltp工具 包括中文分词 词性标注 实体识别 依存句法分析和语义角色标注等 但是其中
  • 多级指针和静动态内存的跨函数访问

    参考 多级指针 静动态内存的跨函数访问 作者 枕上 发布时间 2021 07 15 00 27 17 网址 https blog csdn net jinchi boke article details 118724993 spm 1001
  • RAC安装与维护遇到的几个问题

    author skatetime 2009 05 26 rac安装还是比较顺利的 弄了一天 下面是我在安装和使用中遇到的问题 参考文档 http www oracle com technology pub articles hunter r
  • prisma 开发遇到https://xxx failed, reason: read ECONNRESET

    在使用nodejs prisma 开发时使用如下命令遇到错误 npx prisma db pull 设置proxy和https proxy问题依旧 最后使用 f 参数解决问题 npx prisma db pull f
  • ngModel:numfmt

    angularJS 报 ngModel numfmt angularJS 前台报错 Error ngModel numfmt Model is not of type number 错误 ngModel numfmt模型的类型是 numbe
  • PMD规则

    Design Rules UseSingleton If you have a class that has nothing but static methods consider making it a Singleton Note th
  • Unity常见问题集(待续)

    1 error CS0101 The namespace global already cont 分析 关于global 错误 我们不能打开两个同一名称的scripts在你的工程里 解决 如果在你的工程里有另一个 Activate Trig
  • 傅里叶变换:周期、非周期 与连续、离散

    也是之前总结的 但是感觉很重要 分享出来 也方便自己不带本子的时候能快速找到 傅里叶变化过程中 在两个域 周期和非周期 连续和离散问题
  • chatGPT本地部署

    chatGPT是一种使用自然语言生成 NLG 技术的聊天机器人 可以使用生成对话模型 GPT 训练出来的模型来回答用户的提问或对话 要在本地部署chatGPT 您需要 安装Python环境 并使用pip安装chatGPT所需的依赖包 下载并
  • spring boot 自动构造模拟数据

    spring boot 自动构造模拟数据 引言 Spring boot代码 实体类对象 pom xml 控制器代码 Swagger测试效果 jar包下载地址 引言 现如今基于微服务架构技术开发的项目 一般会采用前后端分离的模式 该模式的好处
  • #3文献学习总结--边缘计算资源分配与任务调度优化

    文献 边缘计算资源分配与任务调度优化综述 1 系统模型 云 边 端 第 1 层是物联网层 传感器 处理器根据应用需求感知 测量和收集原始数据 在本地处理大量数据或将其上传至计算节点 第 2 层是边缘计算层 位于互联网边缘 靠近数据源 边缘计
  • TensorFlow Seq2Seq Model笔记

    0 tf跑起来一直没有用GPU 尴尬 跑起来发现GPU没用起来 CPU满了 发现装错了 应该装tensorflow gpu 代码测试是否用的是GPU https stackoverflow com questions 38009682 ho
  • 正确选择云服务器的带宽教程

    由于云服务器具有弹性的扩容机制 安全的云端集群分布式存储等 云服务器的优势逐渐凸现出来 我们越来越多的人开始选择云服务器 那么如何选择云服务器配置呢 怎样的云服务器配置才能不浪费呢 计算机数据的最小单位是bit 称之为位 其他还有B KB
  • 1114 计算营业额

    题目描述 编程统计营业员一天的营业额 输入要求 输入若干个数据代表交易金额 由于营业员一天完成的交易次数是不确定的 因此最后附加输入一笔0作为交易金额已全部输入结束的标志 输出要求 输出一天的营业额 保留2位小数 输入样例 100 5 12
  • Cocos Creator3D:发布到 Web 平台

    推荐 将 NSDT场景编辑器 加入你的3D工具链 3D工具集 NSDT简石数字孪生 发布到 Web 平台 打开主菜单的 项目 gt 构建发布 打开构建发布面板 Cocos Creator 3D 提供了两种 Web 平台的页面模板 可以通过
  • 虚拟机中安装Virtualbox,嵌套的虚拟机不能运行64位系统

    https www quora com Can I install Virtualbox in a virtual machine Here is a previous question on Quora about it Is it po
  • 机器学习中,不平衡样本多分类评估指标采用哪些?准确率很高,召回率在少数样本上较低。

    Macro F1 这个指标计算每一类的F1 score然后求算术平均 如果模型在小样本上表现不好 小样本的F1会极大程度上拉低Macro F1 除了F1之外还有Macro recall Macro precision 计算原理是一样的 另
  • 区块链在中国(2):PBFT算法

    上一张我们从分布式系统的角度简单叙述了一下 IBM HyperLedger fabric 的一些基本概念 架构和协议信息 其中最为核心的部分就是共识算法 consensus plugin fabric推荐并实现的就是PBFT这一经典算法 B
  • ListView的性能优化之convertView和viewHolder

    ListView优化大致从以下几个角度 1 复用已经生成的convertView 2 添加viewHolder类 3 缓存数据 图片缓存 4 分页加载 一 复用convertView 首先讲下ListView的原理 ListView中的每一