
正文
Android基本控件之ListView(二)<ListView优化>
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
之前我们说到ListView的基本用法。但是,有很多的时候会额外的占用一些内存,从而消耗了性能。既然有消耗性能的可能,那么我们就对其做出相应的优化
我们首先来说说优化的步骤:
第一步、将宽和高设置为填充父窗体,有助于填充item时,避免重复渲染ListView,而导致重复多次调用ListView
第二步、判断getView()方法中的convertView是否为空,如果为空就创建View,不为空就重复使用View
第三步、创建类ViewHolder来解决每次重复查找convertView中的组件
然后,我们就来详细的说一说具体应该如何去优化:
我们首先要创建一个内部类叫做ViewHolder,并在类中维护在item中的各种控件
然后,我们在getView()方法中去维护一个ViewHolder。
然后,我们需要加上一个判断,去判断convertView是否为空,如果为空就证明屏幕显示的还是之前的,并没有新的item进入到屏幕中。
那么,我们需要在其中给convertView赋值(通过布局填充器去实例化)
然后,我们实例化一个ViewHolder
然后,我们需要调用一个setTag()方法把ViewHolder放入到convertView中。
如果convertView不为空,就证明屏幕上显示的item有更新,那么我们就设置item中各个控件要显示的数据。
在此之前,我们需要通过getTag()方法从convertView中获取到Viewholder
最后,返回convertView
优化的过程就是这样。接下来,我们来使用上次的代码再实现一下优化。
我们还是来顺一下思路:
布局文件:
我们需要每个item的布局(一个图标<ImageView>, 一个标题<TextView>,一个内容<TextView>),和主界面布局<ListView>
Activity中:
首先,按照套路,获取控件,设置数据源,设置适配器,设置点击事件
然后我们自定义适配器继承BaseAdapter,并实现其中的方法
在getView方法中先判断convertView是否为空,如果为空就创建一个,如果不为空就设置值
然后,我们定义一个类叫做ViewHodler,并在其中维护item布局中的各种控件
接下来,我们按照我们所想的,来做一个具体的实现:
我们先来看item的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_title"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/iv_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="这是标题"
android:textSize="20sp"/>
<TextView
android:id="@+id/tv_content"
android:layout_toRightOf="@+id/iv_icon"
android:layout_below="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="这是内容"/>
</RelativeLayout>
接下来,我们来看主界面布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
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="application.smile.listview.MainActivity"> <ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
现在,我们的布局文件就准备好了。
接下来,我们来看Activity中的状态:
我们先准备数据源
//存储文字的数组
private String [] names ={"郭嘉", "黄月英", "华佗", "刘备", "陆逊", "吕布", "吕蒙", "马超", "司马懿", "孙权",
"孙尚香", "夏侯惇", "许褚", "杨修", "张飞", "赵云", "甄姬", "周瑜", "诸葛亮"};
//存储图片的数组
private int [] images = {R.mipmap.guojia, R.mipmap.huangyueying, R.mipmap.huatuo, R.mipmap.liubei, R.mipmap.luxun, R.mipmap.lvbu, R.mipmap.lvmeng,
R.mipmap.machao, R.mipmap.simayi, R.mipmap.sunquan, R.mipmap.sunshangxiang, R.mipmap.xiahoudun, R.mipmap.xuchu, R.mipmap.yangxiu,
R.mipmap.zhangfei, R.mipmap.zhaoyun, R.mipmap.zhenji, R.mipmap.zhouyu, R.mipmap.zhugeliang};
然后,我们找到控件:
//找到控件
ListView listView = (ListView) findViewById(R.id.listView);
然后,我们设置适配器:
//设置适配器
listView.setAdapter(new MyAdapter(this));
这里看到了一个MyAdapter,我们一会再说
接下来,我们设置点击事件:
//设置点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//弹出吐司
Toast.makeText(MainActivity.this, "点我了?我是" + names[position], Toast.LENGTH_SHORT).show();
}
});
接下来,我们来看自定义适配器:
该自定义适配器继承了BaseAdapter,并实现其中的4种方法
在重写四种方法之前,我们先维护一个上下文和一个布局填充器,并为其提供一个构造方法去获得一个布局适配器。
//维护一个上下文,为了得到布局填充器
private Context context;
//维护一个布局填充器,为了得到每个item 的布局
private LayoutInflater layoutInflater; public MyAdapter(Context context) {
//通过构造方法获取布局填充器对象
layoutInflater = LayoutInflater.from(context);
}
然后,我们来重写那四个方法:
1.getCount
//该方法是总共有多少个item
@Override
public int getCount() {
return names.length;
}
2.getItem
//该方法是得到每个item的值
@Override
public Object getItem(int position) {
return names[position];
}
3.getItemId
//该方法是得到每个item的id
@Override
public long getItemId(int position) {
return position;
}
4.getView
//该方法是获得视图,也是这些里面最重要的方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
//首先,我们通过布局填充器获得item的布局
convertView = layoutInflater.inflate(R.layout.item_layout, null);
//实例化ViewHodler
viewHolder = new ViewHolder();
//根据item的布局找到图片
viewHolder.iv_icon = (ImageView) convertView.findViewById(iv_icon);
//根据item的布局找到标题
viewHolder.tv_title = (TextView) convertView.findViewById(tv_title);
//根据item的布局找到内容
viewHolder.tv_content = (TextView) convertView.findViewById(tv_content);
//设置tag标记
convertView.setTag(viewHolder);
}
viewHolder = (ViewHolder) convertView.getTag();
//设置图片源(也就是我们装图片的那个数组)
viewHolder.iv_icon.setImageResource(images[position]);
//设置标题文字
viewHolder.tv_title.setText(names[position]);
//设置内容文字
viewHolder.tv_content.setText("我是" + names[position]);
//返回item的布局
return convertView;
}
然后,我们来定义一个内部类,叫做ViewHolder
class ViewHolder {
ImageView iv_icon;
TextView tv_title;
TextView tv_content;
}
我们来简单的整理一个思路
首先,我们定义一个内部类叫做ViewHolder
然后,我们在getView方法中去判断convertView是否为空,如果为空,就通过布局填充器把每个item的布局添加到convertView中。
如果不为空就重复的利用这个布局,并在其中设置数据。
最后,返回convertView
这样,我们的ListView的优化就完成了。
源码奉上:
public class MainActivity extends AppCompatActivity {
//存储文字的数组
private String[] names = {"郭嘉", "黄月英", "华佗", "刘备", "陆逊", "吕布", "吕蒙", "马超", "司马懿", "孙权",
"孙尚香", "夏侯惇", "许褚", "杨修", "张飞", "赵云", "甄姬", "周瑜", "诸葛亮"};
//存储图片的数组
private int[] images = {R.mipmap.guojia, R.mipmap.huangyueying, R.mipmap.huatuo, R.mipmap.liubei, R.mipmap.luxun, R.mipmap.lvbu, R.mipmap.lvmeng,
R.mipmap.machao, R.mipmap.simayi, R.mipmap.sunquan, R.mipmap.sunshangxiang, R.mipmap.xiahoudun, R.mipmap.xuchu, R.mipmap.yangxiu,
R.mipmap.zhangfei, R.mipmap.zhaoyun, R.mipmap.zhenji, R.mipmap.zhouyu, R.mipmap.zhugeliang}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到控件
ListView listView = (ListView) findViewById(R.id.listView);
//设置适配器
listView.setAdapter(new MyAdapter(this));
//设置点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//弹出吐司
Toast.makeText(MainActivity.this, "点我了?我是" + names[position], Toast.LENGTH_SHORT).show();
}
});
} /**
* 自定义适配器,继承BaseAdapter
*/
class MyAdapter extends BaseAdapter {
//维护一个上下文,为了得到布局填充器
private Context context;
//维护一个布局填充器,为了得到每个item 的布局
private LayoutInflater layoutInflater; public MyAdapter(Context context) {
//通过构造方法获取布局填充器对象
layoutInflater = LayoutInflater.from(context);
} //该方法是总共有多少个item
@Override
public int getCount() {
return names.length;
} //该方法是得到每个item的值
@Override
public Object getItem(int position) {
return names[position];
} //该方法是得到每个item的id
@Override
public long getItemId(int position) {
return position;
} //该方法是获得视图,也是这些里面最重要的方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
//首先,我们通过布局填充器获得item的布局
convertView = layoutInflater.inflate(R.layout.item_layout, null);
//实例化ViewHodler
viewHolder = new ViewHolder();
//根据item的布局找到图片
viewHolder.iv_icon = (ImageView) convertView.findViewById(iv_icon);
//根据item的布局找到标题
viewHolder.tv_title = (TextView) convertView.findViewById(tv_title);
//根据item的布局找到内容
viewHolder.tv_content = (TextView) convertView.findViewById(tv_content);
//设置tag标记
convertView.setTag(viewHolder);
}
viewHolder = (ViewHolder) convertView.getTag();
//设置图片源(也就是我们装图片的那个数组)
viewHolder.iv_icon.setImageResource(images[position]);
//设置标题文字
viewHolder.tv_title.setText(names[position]);
//设置内容文字
viewHolder.tv_content.setText("我是" + names[position]);
//返回item的布局
return convertView;
} class ViewHolder {
ImageView iv_icon;
TextView tv_title;
TextView tv_content;
}
}
}
让程序写入生命,将代码融入灵魂
-------smile、zj
Android基本控件之ListView(二)<ListView优化>的更多相关文章- Android基本控件之ListView(一)
我们在使用手机的时候,通常看到,像通讯录,QQ列表样式的东西,这里来解释一下,其实那些都是一个ListView 今天,我们就来详细的讲解一下ListView这个控件 ListView中每条显示的数据都 ...
- Android基础控件ListView基础操作
1.简介 基于Android基础控件ListView和自定义BaseAdapter适配器情况下,对ListView的数据删除和添加操作: public boolean add(E e) {//添加数据 ...
- Android高级控件(一)——ListView绑定CheckBox实现全选,增加和删除等功能
Android高级控件(一)--ListView绑定CheckBox实现全选,增加和删除等功能 这个控件还是挺复杂的,也是项目中应该算是比较常用的了,所以写了一个小Demo来讲讲,主要是自定义adap ...
- Android高级控件(一)——ListView绑定CheckBox实现全选,添加和删除等功能
Android高级控件(一)--ListView绑定CheckBox实现全选,添加和删除等功能 这个控件还是挺复杂的.也是项目中应该算是比較经常使用的了,所以写了一个小Demo来讲讲,主要是自己定义a ...
- Android 基本控件相关知识整理
Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户.作为一个程序员如何才能开发出友好的图形界 ...
- Android 开源控件与常用开发框架开发工具类
Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...
- Android 开源控件系列_2
FileBrowserView 一个强大的文件选择控件.界面比较漂亮,使用也很简单.特点:可以自定义UI:支持复制.剪切.删除.移动文件:可以用在Fragment.ativity.DialogFrag ...
- Github上star数超1000的Android列表控件
Android开发中,列表估计是最最常使用到的控件之一了.列表相关的交互如下拉刷新,上拉更多,滑动菜单,拖动排序,滑动菜单,sticky header分组,FAB等等都是十分常见的体验.Github中 ...
- Android UI控件常用库汇总
现在App的开发已经是非常成熟,涌现了一大批开源的工具.这些项目能够提高我们的搬砖效率.以下是一些在开发中比较常使用的控件和库. ListView WaveSwipeRefreshLayout 水滴效 ...
- Android基本控件之Menus
在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...
随机推荐- Java基础之类的初始化顺序
对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是 (静态变量.静态初始化块)>(变量.初始化块)>构造器 对于继承的情况: 1. 父类--静态变量 2. 父 ...
- Makefile 一点一滴(三)—— 尝试简单的变量替换
上一版的 makefile: TestCpp : ./debug/TestCpp.o g++ -o TestCpp ./debug/TestCpp.o ./debug/TestCpp.o : ./sr ...
- 新浪微博客户端(63)-使用block进行链式编程
Person.h #import <Foundation/Foundation.h> @interface Person : NSObject - (Person *(^)())study ...
- linux下文件系统类型的学习
1. 以超级用户权限登陆Linux,进入 /lib/modules/2.6.32--504.el6.x86_64/kernel/fs目录执行 ls 命令(不同Linux发行版本的Fs目录有些不同你可 ...
- WPF 之 自定义窗体标题栏
在WPF中自定义窗体标题栏,首先需要将窗体的WindowStyle属性设置为None,隐藏掉WPF窗体的自带标题栏.然后可以在窗体内部自定义一个标题栏. 例如,标题栏如下: <WrapPanel ...
- xcode中如何安装多个版本的模拟器
在xcode里面,安装的时间默认自带的有模拟器,有时间为了调试需要使用个多个版本的模拟器 在xcode -> preference 里面 选择download,这里你可下载你需要的模拟器
- spark快速入门之最简配置 spark 1.5.2 hadoop 2.7 配置
配置的伪分布式,ubuntu14.04上 先配置hadoop,参见这个博客,讲的很好 http://www.powerxing.com/install-hadoop/, 但是我在配的过程中还是遇到了问 ...
- Metasploit学习之msf连接数据库
kali使用metasploit开启数据服务: 首先,初次使用系统要初始化建立数据库msf3, 否则的话 /opt/metasploit/apps/pro/ui/config/databse.yml不 ...
- Java 集合 HashMap &; HashSet 拾遗
Java 集合 HashMap & HashSet 拾遗 @author ixenos 摘要:HashMap内部结构分析 Java HashMap采用的是冲突链表方式 从上图容易看出,如果选择 ...
- 微信小程序用户信息解密失败导致的内存泄漏问题。
微信小程序获取用户解密的Session_key 然后对 encryptedData进行解密 偶尔报错 时间长了之后会报内存溢出: java.lang.OutOfMemoryError: GC over ...
我们在使用手机的时候,通常看到,像通讯录,QQ列表样式的东西,这里来解释一下,其实那些都是一个ListView 今天,我们就来详细的讲解一下ListView这个控件 ListView中每条显示的数据都 ...
1.简介 基于Android基础控件ListView和自定义BaseAdapter适配器情况下,对ListView的数据删除和添加操作: public boolean add(E e) {//添加数据 ...
Android高级控件(一)--ListView绑定CheckBox实现全选,增加和删除等功能 这个控件还是挺复杂的,也是项目中应该算是比较常用的了,所以写了一个小Demo来讲讲,主要是自定义adap ...
Android高级控件(一)--ListView绑定CheckBox实现全选,添加和删除等功能 这个控件还是挺复杂的.也是项目中应该算是比較经常使用的了,所以写了一个小Demo来讲讲,主要是自己定义a ...
Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户.作为一个程序员如何才能开发出友好的图形界 ...
Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...
FileBrowserView 一个强大的文件选择控件.界面比较漂亮,使用也很简单.特点:可以自定义UI:支持复制.剪切.删除.移动文件:可以用在Fragment.ativity.DialogFrag ...
Android开发中,列表估计是最最常使用到的控件之一了.列表相关的交互如下拉刷新,上拉更多,滑动菜单,拖动排序,滑动菜单,sticky header分组,FAB等等都是十分常见的体验.Github中 ...
现在App的开发已经是非常成熟,涌现了一大批开源的工具.这些项目能够提高我们的搬砖效率.以下是一些在开发中比较常使用的控件和库. ListView WaveSwipeRefreshLayout 水滴效 ...
在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...
- Java基础之类的初始化顺序
对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是 (静态变量.静态初始化块)>(变量.初始化块)>构造器 对于继承的情况: 1. 父类--静态变量 2. 父 ...
- Makefile 一点一滴(三)—— 尝试简单的变量替换
上一版的 makefile: TestCpp : ./debug/TestCpp.o g++ -o TestCpp ./debug/TestCpp.o ./debug/TestCpp.o : ./sr ...
- 新浪微博客户端(63)-使用block进行链式编程
Person.h #import <Foundation/Foundation.h> @interface Person : NSObject - (Person *(^)())study ...
- linux下文件系统类型的学习
1. 以超级用户权限登陆Linux,进入 /lib/modules/2.6.32--504.el6.x86_64/kernel/fs目录执行 ls 命令(不同Linux发行版本的Fs目录有些不同你可 ...
- WPF 之 自定义窗体标题栏
在WPF中自定义窗体标题栏,首先需要将窗体的WindowStyle属性设置为None,隐藏掉WPF窗体的自带标题栏.然后可以在窗体内部自定义一个标题栏. 例如,标题栏如下: <WrapPanel ...
- xcode中如何安装多个版本的模拟器
在xcode里面,安装的时间默认自带的有模拟器,有时间为了调试需要使用个多个版本的模拟器 在xcode -> preference 里面 选择download,这里你可下载你需要的模拟器
- spark快速入门之最简配置 spark 1.5.2 hadoop 2.7 配置
配置的伪分布式,ubuntu14.04上 先配置hadoop,参见这个博客,讲的很好 http://www.powerxing.com/install-hadoop/, 但是我在配的过程中还是遇到了问 ...
- Metasploit学习之msf连接数据库
kali使用metasploit开启数据服务: 首先,初次使用系统要初始化建立数据库msf3, 否则的话 /opt/metasploit/apps/pro/ui/config/databse.yml不 ...
- Java 集合 HashMap &; HashSet 拾遗
Java 集合 HashMap & HashSet 拾遗 @author ixenos 摘要:HashMap内部结构分析 Java HashMap采用的是冲突链表方式 从上图容易看出,如果选择 ...
- 微信小程序用户信息解密失败导致的内存泄漏问题。
微信小程序获取用户解密的Session_key 然后对 encryptedData进行解密 偶尔报错 时间长了之后会报内存溢出: java.lang.OutOfMemoryError: GC over ...






