zoukankan      html  css  js  c++  java
  • ListView的自定义适配器及其优化(listView序号混乱问题的处理)

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

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

    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 }
    View Code

    我之前一直是使用上面的代码来写自定义适配器的,但是这种方式仅仅限于一些简单的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 }
    View Code

    其实对于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 }
    View Code

    优化后的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 }
    View Code

    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     });
    View Code

    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" /> 
    View Code

    优化后的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" />
    View Code

    5.减少item的布局的深度

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

    6.使用ViewHolder

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

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

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

  • 相关阅读:
    线程中消费者生产者的实例代码(synchronized关键字)
    ThreadLocal管理Connection
    ThreadLocal的练习代码
    JDK中线程组ThreadGroup
    创建线程的三种方式
    ES练习代码
    window下在同一台机器上安装多个版本jdk,修改环境变量不生效问题处理办法
    ES配置文件中文版
    springmvc工作原理
    IE不兼容document.getElementsByClassName
  • 原文地址:https://www.cnblogs.com/1925yiyi/p/7443818.html
Copyright © 2011-2022 走看看