ListView是最常使用的android组件之一,关于listView的优化问题刚刚了解了一些,在这里做出总结。

PS:如果想让ListView中的item根据数据内容显示item的大小,需要在item.xml中增加下面一句话就可以了(是在整体的布局文件上加):

  1. android:minHeight="?android:attr/listPreferredItemHeight"
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:id="@+id/item"
  6. android:minHeight="?android:attr/listPreferredItemHeight"
  7. android:orientation="horizontal" >
  8. </LinearLayout>

优化前的自定义适配器:

  1. package com.anhua.adapter;
  2.  
  3. import java.util.List;
  4. import java.util.Map;
  5.  
  6. import com.anhua.bean.LocalHuoDanBean;
  7. import com.example.imooc_weixinfragment.R;
  8.  
  9. import android.content.Context;
  10. import android.view.LayoutInflater;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.BaseAdapter;
  14. import android.widget.TextView;
  15.  
  16. public class HuoChangAadpter extends BaseAdapter {
  17. private TextView title;// 承运号
  18. private TextView number;// 缺货件数
  19. private TextView no;//序号
  20. private List<Map<String, Object>> arrayList;
  21. private Context context;// 运行上下文
  22. private int item;
  23. private LayoutInflater inflater;
  24. public HuoChangAadpter(List<Map<String, Object>> arrayList, int item,
  25. Context context) {
  26. this.arrayList = arrayList;
  27. this.context = context;
  28. this.item = item;
  29. this.inflater = LayoutInflater.from(context);// 创建视图容器并设置上下文
  30. }
  31. @Override
  32. public int getCount() {
  33. // TODO Auto-generated method stub
  34. return arrayList.size();
  35. }
  36.  
  37. @Override
  38. public Object getItem(int position) {
  39. // TODO Auto-generated method stub
  40. return arrayList.get(position);
  41. }
  42.  
  43. @Override
  44. public long getItemId(int position) {
  45. // TODO Auto-generated method stub
  46. return 0;
  47. }
  48.  
  49. @Override
  50. public View getView(int position, View convertView, ViewGroup parent) {
  51. if (convertView == null) {
  52. convertView = inflater.inflate(item, null);
  53. title = (TextView) convertView.findViewById(R.id.chengyun);
  54. number = (TextView) convertView.findViewById(R.id.number);
  55. no=(TextView) convertView.findViewById(R.id.no);
  56. }
  57. String titles = arrayList.get(position).get("ID").toString();// 承运号
  58. String numbers = arrayList.get(position).get("quantity").toString();// 缺货件数
  59. String nos=(position+1)+"";
  60. no.setText(nos);
  61. title.setText(titles);
  62. number.setText(numbers);
  63. return convertView;
  64. }
  65. }

我之前一直是使用上面的代码来写自定义适配器的,但是这种方式仅仅限于一些简单的Item组件。最近遇到了给listView的数据增加序号排序的问题,使用优化前的代码直接造成序号的书序错乱,而使用下面的优化后的代码序号排序错乱问题就解决了。

优化后的自定义适配器:

  1. package com.anhua.adapter;
  2.  
  3. import java.util.List;
  4. import java.util.Map;
  5.  
  6. import com.anhua.bean.LocalHuoDanBean;
  7. import com.example.imooc_weixinfragment.R;
  8.  
  9. import android.content.Context;
  10. import android.view.LayoutInflater;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.BaseAdapter;
  14. import android.widget.TextView;
  15.  
  16. public class HuoChangAadpter extends BaseAdapter {
  17.  
  18. private List<Map<String, Object>> arrayList;
  19. private Context context;// 运行上下文
  20. private int item;
  21. private LayoutInflater inflater;
  22.  
  23. public HuoChangAadpter(List<Map<String, Object>> arrayList, int item,
  24. Context context) {
  25. this.arrayList = arrayList;
  26. this.context = context;
  27. this.item = item;
  28. this.inflater = LayoutInflater.from(context);// 创建视图容器并设置上下文
  29. }
  30.  
  31. @Override
  32. public int getCount() {
  33. // TODO Auto-generated method stub
  34. return arrayList.size();
  35. }
  36.  
  37. @Override
  38. public Object getItem(int position) {
  39. // TODO Auto-generated method stub
  40. return arrayList.get(position);
  41. }
  42.  
  43. @Override
  44. public long getItemId(int position) {
  45. // TODO Auto-generated method stub
  46. return 0;
  47. }
  48.  
  49. @Override
  50. public View getView(int position, View convertView, ViewGroup parent) {
  51. ViewHolder holder = null;
  52. if (convertView == null) {
  53. convertView = inflater.inflate(item, null);
  54. holder = new ViewHolder();
  55.  
  56. holder.title = (TextView) convertView.findViewById(R.id.chengyun);
  57. holder.number = (TextView) convertView.findViewById(R.id.number);
  58. holder.no = (TextView) convertView.findViewById(R.id.no);
  59. convertView.setTag(holder);
  60. } else {
  61. // viewHolder被复用
  62. holder = (ViewHolder) convertView.getTag();
  63. }
  64. String titles = arrayList.get(position).get("ID").toString();// 承运号
  65. String numbers = arrayList.get(position).get("quantity").toString();// 缺货件数
  66. String nos = (position + 1) + "";
  67. holder.no.setText(nos);
  68. holder.title.setText(titles);
  69. holder.number.setText(numbers);
  70. return convertView;
  71. }
  72.  
  73. private class ViewHolder {
  74. private TextView title;// 承运号
  75. private TextView number;// 缺货件数
  76. private TextView no;// 序号
  77. }
  78. }

其实对于listView的优化方案可以从以下角度来考虑:

  • 1.在adapter中的getView方法中尽量少使用逻辑
  • 2.尽最大可能避免GC
  • 3.滑动的时候不加载图片
  • 4.将ListView的scrollingCache和animateCache设置为false
  • 5.item的布局层级越烧越好
  • 6.使用ViewHolder

1.在adapter中的getView方法中尽量少使用逻辑

不要在你的getView()中写过多的逻辑代码,我们可以将这些代码放在别的地方,例如:

优化前的getView():

  1. @Override
  2. public View getView(int position, View convertView, ViewGroup paramViewGroup) {
  3. Object current_event = mObjects.get(position);
  4. ViewHolder holder = null;
  5. if (convertView == null) {
  6. holder = new ViewHolder();
  7. convertView = inflater.inflate(R.layout.row_event, null);
  8. holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
  9. holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
  10. convertView.setTag(holder);
  11.  
  12. } else {
  13. holder = (ViewHolder) convertView.getTag();
  14. }
  15.  
  16. //在这里进行逻辑判断,这是有问题的
  17. if (doesSomeComplexChecking()) {
  18. holder.ThreeDimention.setVisibility(View.VISIBLE);
  19. } else {
  20. holder.ThreeDimention.setVisibility(View.GONE);
  21. }
  22.  
  23. // 这是设置image的参数,每次getView方法执行时都会执行这段代码,这显然是有问题的
  24. RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
  25. holder.EventPoster.setLayoutParams(imageParams);
  26.  
  27. return convertView;
  28. }

优化后的getView():

  1. @Override
  2. public View getView(int position, View convertView, ViewGroup paramViewGroup) {
  3. Object object = mObjects.get(position);
  4. ViewHolder holder = null;
  5.  
  6. if (convertView == null) {
  7. holder = new ViewHolder();
  8. convertView = inflater.inflate(R.layout.row_event, null);
  9. holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
  10. holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
  11. //设置参数提到这里,只有第一次的时候会执行,之后会复用
  12. RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
  13. holder.EventPoster.setLayoutParams(imageParams);
  14. convertView.setTag(holder);
  15. } else {
  16. holder = (ViewHolder) convertView.getTag();
  17. }
  18.  
  19. // 我们直接通过对象的getter方法代替刚才那些逻辑判断,那些逻辑判断放到别的地方去执行了
  20. holder.ThreeDimension.setVisibility(object.getVisibility());
  21.  
  22. return convertView;
  23. }

2.GC 垃圾回收器

当你创建了大量的对象的时候,GC就会频繁的执行,所以在getView()方法中不要创建很多的对象,最好的优化是,不要在ViewHolder以外创建任何对象,如果你的你的log里面发现“GC has freed some memory”频繁出现的话,那你的程序肯定有问题了。你可以检查一下:
a) item布局的层级是否太深
b) getView()方法中是否有大量对象存在
c) ListView的布局属性

3.加载图片

如果你的ListView中需要显示从网络上下载的图片的话,我们不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,所以我们需要再监听器里面监听ListView的状态,如果滑动的时候,停止加载图片,如果没有滑动,则开始加载图片

  1. listView.setOnScrollListener(new OnScrollListener() {
  2.  
  3. @Override
  4. public void onScrollStateChanged(AbsListView listView, int scrollState) {
  5. //停止加载图片
  6. if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
  7. imageLoader.stopProcessingQueue();
  8. } else {
  9. //开始加载图片
  10. imageLoader.startProcessingQueue();
  11. }
  12. }
  13.  
  14. @Override
  15. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
  16. // TODO Auto-generated method stub
  17.  
  18. }
  19. });

4.将ListView的scrollingCache和animateCache设置为false

scrollingCache: scrollingCache本质上是drawing cache,你可以让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,但是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们可以手动将它关闭。

animateCache: ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们可以手动将它关闭掉

优化前的ListView

  1. <ListView
  2. android:id="@android:id/list"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:cacheColorHint="#00000000"
  6. android:divider="@color/list_background_color"
  7. android:dividerHeight="0dp"
  8. android:listSelector="#00000000"
  9. android:smoothScrollbar="true"
  10. android:visibility="gone" />

优化后的ListView

  1. <ListView
  2. android:id="@android:id/list"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:divider="@color/list_background_color"
  6. android:dividerHeight="0dp"
  7. android:listSelector="#00000000"
  8. android:scrollingCache="false"
  9. android:animationCache="false"
  10. android:smoothScrollbar="true"
  11. android:visibility="gone" />

5.减少item的布局的深度

我们应该尽量减少item布局深度,因为当滑动ListView的时候,这回直接导致测量与绘制,因此会浪费大量的时间,所以我们应该将一些不必要的布局嵌套关系去掉。减少item布局深度

6.使用ViewHolder

这个大家应该非常熟悉了,但是不要小看这个ViewHolder,它可以大大提高我们ListView的性能

ListView的优化我们已经讲完了,如果在你的项目中,这些基本优化你还没有做到的话,那么你的ListView是有问题的,还有很大的提升潜力,以后再使用ListView的时候,一定要将这几点考虑进去,发挥它的最大的性能。

参考文章:http://blog.csdn.net/nugongahou110/article/details/47128125

ListView的自定义适配器及其优化(listView序号混乱问题的处理)的更多相关文章

  1. 细解ListView之自定义适配器

    下面我们将以一个例子来讲述ListView之自定义适配器 首先我们看一下效果图: [分析] 首先:需要创建一个ListView控件,自定义适配器是为了实现自定义ListView的ListView_It ...

  2. ListView(下)自定义适配器

    (一) 1.效果图 2.activity_main.xml <?xml version="1.0" encoding="utf-8"?> <L ...

  3. Android -- ListView(SimpleAdapter) 自定义适配器

    aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA ...

  4. ListView使用自定义适配器的情况下实现适配器的文本和图标控件点击事件执行Activity界面中的方法

    ListView使用的是自定义适配器,列表项的布局文件中含有文本和图标,实现文本区域和图标区域的点击事件. 实现思路:在自定义适配器MyArrayAdapter 类型中自定义接口和接口方法,分别设置文 ...

  5. ListView使用自定义适配器的情况下实现适配器的控件点击事件执行Activity界面中的方法

    如果ListView使用的是自定义的适配器,比如MyArrayAdapter extends ArrayAdapter<String> 那么,如何实现适配器中的点击事件执行activity ...

  6. 安卓开发_浅谈ListView(自定义适配器)

    ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果 有这样一个Demo ...

  7. (转)Android之自定义适配器

    ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果. 有这样一个Demo ...

  8. 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)

    1.listview入门,自定义的数据适配器 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/and ...

  9. 打造android偷懒神器———ListView的万能适配器

    如果你去做任何一个项目,我相信你都会跟我有一样的经历,最最普遍的就是列表显示ListView,当然,写N个自定义的适配器也是情理之中.虽说程序员本身就是搬砖,做这些枯燥无味的重复的事情也是理所当然,但 ...

随机推荐

  1. ArcGIS案例学习笔记-聚类点的空间统计特征

    ArcGIS案例学习笔记-聚类点的空间统计特征 联系方式:谢老师,135-4855-4328,xiexiaokui@qq.com 目的:对于聚集点,根据分组字段case field,计算空间统计特征 ...

  2. ubuntu上装MySQL遇到的问题及解决办法

    验证原有主机上是否已安装mysql                运行sudo netstat -tap | grep mysql命令查看是否有Mysql的端口 查看到mysql已安装上了: 启动my ...

  3. centos 安装python3.6

    环境准备 yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel 首先去官网下 ...

  4. poj2115-Looooops-(扩展欧几里得定理)

    C Looooops Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:33752   Accepted: 9832 Descri ...

  5. Latex公式示范

    \(A_\alpha(x)\)      \(\qquad\)      \(a^2+b^2=c^2 \)      \(\qquad\)      \(\sum\limits_{m=0}^\inft ...

  6. 对于“2017面向对象程序设计(Java)第就十周学习总结”存在问题的反馈

    1.“学生们普遍反映对泛型相关知识点的理解有一些难度,而且对泛型有关程序的编写有些困难.希望老师再次讲解.同学们普遍反映第四.第五个实验较难,大部分同学不能独立完成实验,希望老师能在课堂上详细解答.根 ...

  7. Dubbo -- Simple Monitor

    一.简介 dubbo-monitor-simple是dubbo提供的简单监控中心,可以用来显示接口暴露,注册情况,也可以看接口的调用明细,调用时间等. Simple Monitor挂掉不会影响到Con ...

  8. canvas 动画 时钟clock

    <canvas id="clock" width="500" height="500"></canvas> func ...

  9. 【C++】cout未刷新缓冲区仍会输出的问题

    众所周知,cout是一个流对象,管理一个缓冲区.当使用<<操作符输出字符串时,字符串不是直接被输出到屏幕上,而是首先被插入到该流的缓存(buffer)中.而只有当缓冲区被刷新时,字符串才会 ...

  10. ORA-01555 snapshot too old

    假设有一张6000万行数据的testdb表,预计testdb全表扫描1次需要2个小时,参考过程如下: 1.在1点钟,用户A发出了select * from testdb;此时不管将来testdb怎么变 ...