之所以说 ListView 这个控件很难用,就是因为它有很多的细节可以优化,其中运行效率 就是很重要的一点。目前我们 ListView 的运行效率是很低的,因为在 FruitAdapter 的 getView() 方法中每次都将布局重新加载了一遍,当 ListView 快速滚动的时候这就会成为性能的瓶颈。

仔细观察,getView()方法中还有一个 convertView 参数,这个参数用于将之前加载好的 布局进行缓存,以便之后可以进行重用。修改 FruitAdapter 中的代码,如下所示:

public class FruitAdapter extends ArrayAdapter<Fruit> {

……

@Override

public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position);

View view;

if (convertView == null) {

view = LayoutInflater.from(getContext()).inflate(resourceId, null);

} else {

view = convertView;

}

ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName());

return view;

}

}

可以看到,现在我们在 getView()方法中进行了判断,如果 convertView 为空,则使用 LayoutInflater 去加载布局,如果不为空则直接对 convertView 进行重用。这样就大大提高了
ListView 的运行效率,在快速滚动的时候也可以表现出更好的性能。

不过,目前我们的这份代码还是可以继续优化的,虽然现在已经不会再重复去加载布局,
但是每次在 getView()方法中还是会调用 View 的 findViewById()方法来获取一次控件的实例。
我们可以借助一个 ViewHolder 来对这部分性能进行优化,修改 FruitAdapter 中的代码,如下
所示:

public class FruitAdapter extends ArrayAdapter<Fruit> {

……

@Override

public View getView(int position, View convertView, ViewGroup parent) { Fruit
fruit = getItem(position);

View view;

ViewHolder viewHolder;

if (convertView == null) {

view = LayoutInflater.from(getContext()).inflate(resourceId, null);

viewHolder = new ViewHolder();

viewHolder.fruitImage = (ImageView) view.findViewById

(R.id.fruit_image);

viewHolder.fruitName = (TextView) view.findViewById

(R.id.fruit_name);

view.setTag(viewHolder); // ViewHolder存储在View

} else {

view = convertView;

viewHolder = (ViewHolder) view.getTag();
//
重新获取ViewHolder

}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());

return view;

}

class ViewHolder { ImageView fruitImage;
TextView fruitName;

}

}

我们新增了一个内部类 ViewHolder,用于对控件的实例进行缓存。当 convertView 为空 的时候,创建一个 ViewHolder 对象,并将控件的实例都存放在 ViewHolder 里,然后调用 View 的 setTag()方法,将 ViewHolder 对象存储在 View 中。当 convertView 不为空的时候则调用 View 的 getTag()方法,把 ViewHolder 重新取出。这样所有控件的实例都缓存在了 ViewHolder
里,就没有必要每次都通过 findViewById()方法来获取控件实例了。

通过这两步的优化之后,我们 ListView 的运行效率就已经非常不错了。

3.5.4    ListView 的点击事件

话说回来,ListView 的滚动毕竟只是满足了我们视觉上的效果,可是如果 ListView 中的 子项不能点击的话,这个控件就没有什么实际的用途了。因此,本小节中我们就来学习一下 ListView 如何才能响应用户的点击事件。

修改 MainActivity 中的代码,如下所示:

public class MainActivity extends Activity {

private List<Fruit> fruitList = new
ArrayList<Fruit>();

@Override

protected void
onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initFruits();

FruitAdapter adapter = new
FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList);

ListView listView = (ListView)
findViewById(R.id.list_view); listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {

@Override

public void
onItemClick(AdapterView<?> parent, View view, int position, long id) {

Fruit fruit = fruitList.get(position);
Toast.makeText(MainActivity.this, fruit.getName(),

Toast.LENGTH_SHORT).show();

}

});

}

……

}

可以看到,我们使用了 setOnItemClickListener()方法来为 ListView 注册了一个监听器,
当用户点击了 ListView 中的任何一个子项时就会回调 onItemClick()方法,在这个方法中可以
通过
position 参数判断出用户点击的是哪一个子项,然后获取到相应的水果,并通过 Toast 将水果的名字显示出来。

重新运行程序,并点击一下西瓜,效果如图 3.31 所示。

图   3.31

android:提升 ListView 的运行效率的更多相关文章

  1. Android笔记——提升ListView的运行效率

    之所以说 ListView 这个控件很难用,就是因为它有很多的细节可以优化,其中运行效率就是很重要的一点.目前我们ListView 的运行效率是很低的,因为在 FruitAdapter 的getVie ...

  2. 初识ListView - 定制ListView - 提升ListView运行效率

    ListView绝对可以称得上是 Android 中最常用的控件之一,几乎所有的应用程序都会用到它.由于手机屏幕空间都比较有限,能够一次性在屏幕上显示的内容并不多,当我们的程序中有大量的数据需要展示的 ...

  3. Android中ListView实现图文并列并且自定义分割线(完善仿微信APP)

    昨天的(今天凌晨)的博文<Android中Fragment和ViewPager那点事儿>中,我们通过使用Fragment和ViewPager模仿实现了微信的布局框架.今天我们来通过使用Li ...

  4. Android中ListView的用法

    使用方法1 显示简单的文本 在layout文件中像加入普通控件一样在layout文件中引入ListView <ListView android:id="@+id/list_view&q ...

  5. java攻城狮之路(Android篇)--ListView与ContentProvider

    一.ListView 1.三种Adapter构建ListView ListView添加条目的时候, 可以使用setAdapter(ListAdapter)方法, 常用的ListAdapter有三种 B ...

  6. 43.Android之ListView中BaseAdapter学习

    实际开发中个人觉得用的比较多是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜欢的列表布局,比如ListView.GridView.Gallery.Spinner ...

  7. Android杂谈--ListView之BaseAdapter的使用

    话说开发用了各种Adapter之后感觉用的最舒服的还是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜欢的列表布局,比如ListView.GridView.Gal ...

  8. Android在ListView显示图片(重复混乱闪烁问题)

    Android在ListView显示图片(重复混乱闪烁问题) 1.原因分析 ListView item缓存机制: 为了使得性能更优,ListView会缓存行item(某行相应的View). ListV ...

  9. Android在ListView滑动数据混乱

    我相信做过Android应用程序开发或多或少都遇到了这个问题.或者是在ListView数据损坏幻灯片事件.要么GridView数据损坏幻灯片事件. 让我们来看看一个网友写的文章,个人感觉还不错的文章: ...

随机推荐

  1. ThinkPHP 框架2.1,2.2和3.0版本开启lite模式导致URL命令执行漏洞

    在开启了Lite模式后,在ThinkPHP/extend/Mode/Lite/Dispatcher.class.php中第73行: // 解析剩余的URL参数 $res = preg_replace( ...

  2. python3内存存储几种数据类型对差异

    列表,元组,集合,字典几种数据类型差异 列表: list=[0,1,'a'] 元组:list=(0,1,'a') 集合 :list=[0,1,'a'] 字典:list={name:'tom',age: ...

  3. oracle进阶之connect by笔记

    本博客是自己在学习和工作途中的积累与总结,仅供自己参考,也欢迎大家转载,转载时请注明出处. http://www.cnblogs.com/king-xg/p/6794562.html 如果觉得对您有帮 ...

  4. TestNG测试方法

    @Test(enabled = false)有助于禁用此测试用例. 分组测试是TestNG中的一个新的创新功能,使用<groups>标记在testng.xml文件中指定分组. 它可以在&l ...

  5. python 全栈开发,Day93(vue内容补充,VueX)

    昨日内容回顾 1. 页面的布局 Vue中使用Bootstrap搭页面 1. 安装 1. npm install bootstrap@3.3.7 -S 2. 使用 1. import 'bootstra ...

  6. ubuntu基本用法

    • Linux上vim编辑器缩进的设置 • 从零开始UNIX环境高级编程(0):Linux下运行第一个程序

  7. JDK的get请求方式

    package com.example.wang.testapp3; import android.app.ProgressDialog; import android.os.Bundle; impo ...

  8. 《Java程序性能优化》之设计优化

    豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞 ...

  9. BZOJ4997 [Usaco2017 Feb]Why Did the Cow Cross the Road III

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4997 题意概括 在n*n的区域里,每一个1*1的块都是一个格子. 有k头牛在里面. 有r个篱笆把格 ...

  10. 6-6 小球下落 uva679

    较为简单的找规律题目 开始认识二叉树  虽然这题和二叉树没有啥关系 #include<bits/stdc++.h> using namespace std; int main() { in ...