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 ...
随机推荐
- 对Spring的理解
1.Spring实现了工厂模式的工厂类,这个类名为BeanFactory实际上是一个接口,在程序中通常BeanFactory的子类ApplicationContext.Spring相当于一个大的工厂类 ...
- 如何利用WordPress创建自定义注册表单插件
来源:http://www.ido321.com/1031.html 原文:Creating a Custom WordPress Registration Form Plugin 译文:创建一个定制 ...
- iOS开发相关图书推荐
Objective-C编程之道:iOS设计模式解析 作 者 [美] Carlo Chung 著:刘威 译 出 版 社 人民邮电出版社 出版时间 2011-11-01 版 次 1 页 ...
- 瞬间从IT屌丝变大神——注释规则
注释的主要规则如下: 公共组件和各栏目的维护者都需要在文件头部加上注释说明: /** *文件用途说明 *作者姓名 *联系方式*制作日期 **/ 大的模块注释方法: //======= //代码用途 / ...
- 只有IE能上网,其他浏览器均不可以!
今天起来,高高兴兴的来到实验室,发现电脑打开上不了网.本人平时喜欢用Chrome,发现上不了网,就开始ping.发现可以ping通,但是网页打不开! 第一反应是DNS的问题,可以发现DNS没问题,能正 ...
- Lucene学习笔记: 四,Lucene索引过程分析
对于Lucene的索引过程,除了将词(Term)写入倒排表并最终写入Lucene的索引文件外,还包括分词(Analyzer)和合并段(merge segments)的过程,本次不包括这两部分,将在以后 ...
- CDH版HDFS Block Balancer方法
命令: sudo -u hdfs hdfs balancer 默认会检查每个datanode的磁盘使用情况,对磁盘使用超过整个集群10%的datanode移动block到其他datanode达到均衡作 ...
- Java——泛型(最易懂的方式讲解泛型)
来自: 代码大湿 代码大湿 写在前面: 只要认真看过,基本能很熟悉泛型的特性.泛型是JDK1.5之后出现的,比如JDK1.5之前的ArrayList,会出现2个问题 1:向ArrayList当中添加对 ...
- MySQL索引的创建,查看,删除
在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX或ALTER TABLE来为表增加索引. 1.ALTER TABLE ALTER TABLE用来创建普通索引.UN ...
- codeforces 651B Beautiful Paintings
B. Beautiful Paintings time limit per test 1 second memory limit per test 256 megabytes input standa ...