zoukankan      html  css  js  c++  java
  • 【Android笔记】listview加载性能优化及有多种listitem布局处理方式

    在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容。

    用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建。

     

    ListView加载数据都是在

    1 public View getView(int position, View convertView, ViewGroup parent) {
    2 
    3   。。。。。。
    4 
    5 }

    方法中进行的(要自定义listview都需要重写listadapter:如 BaseAdapter,SimpleAdapter,CursorAdapter的等的getvView方法),

    优化listview的加载速度就要让 convertView匹配列表类型,并最大程度上的重新使用convertView

     

    其中,getview的加载方法一般有以下三种加载方式:

    1、最慢的加载方式是每一次都重新定义一个View载入布局,再加载数据

     1  public View getView(int position, View convertView, ViewGroup parent) {
     2 
     3      View item = mInflater.inflate(R.layout.list_item_icon_text, null);
     4 
     5      ((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
     6 
     7      ((ImageView) item.findViewById(R.id.icon)).setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
     8 
     9      return item;
    10 
    11 }

    2、正确的加载方式是当convertView不为空的时候直接重新使用convertView从而减少了很多不必要的View的创建,然后加载数据

     1  public View getView(int position, View convertView, ViewGroup parent) {
     2 
     3      if (convertView == null) {
     4 
     5          convertView = mInflater.inflate(R.layout.item, parent, false);
     6 
     7      }
     8 
     9      ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
    10 
    11      ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
    12 
    13  
    14 15 return convertView; 16 17 }

    3、最快的方式是定义一个ViewHolder,将convetView的tag设置为ViewHolder,不为空时重新使用即可

     1 static class ViewHolder {
     2 
     3     TextView text;
     4 
     5     ImageView icon;
     6 
     7 }
     8 
     9  
    10 
    11 public View getView(int position, View convertView, ViewGroup parent) {
    12 
    13     ViewHolder holder;
    14 
    15     if (convertView == null) {
    16 
    17     convertView = mInflater.inflate(R.layout.list_item_icon_text,parent, false);
    18 
    19     holder = new ViewHolder();
    20 
    21     holder.text = (TextView) convertView.findViewById(R.id.text);
    22 
    23     holder.icon = (ImageView) convertView.findViewById(R.id.icon);
    24 
    25     convertView.setTag(holder);
    26 
    27 } else {
    28 
    29     holder = (ViewHolder) convertView.getTag();
    30 
    31 }
    32 
    33     holder.text.setText(DATA[position]);
    34 
    35     holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 :mIcon2);
    36 
    37     return convertView;
    38 
    39 }

    三种方式加载效率对比如下图所示:

    说明:上述三个例子代码摘自google 2010 I/O大会

     

    当处理一些耗时的资源加载的时候需要做到以下几点,以使你的加载更快更平滑:

    1.   适配器在界面主线程中进行修改

    2.   可以在任何地方获取数据但应该在另外一个地方请求数据

    3.   在主界面的线程中提交适配器的变化并调用notifyDataSetChanged()方法

     

    ===============================分割线=========================================

     

    那么如果存在多个item样式如何处理呢??

    大致思路就是创建多个viewholder,在getViewType的时候设置不同位置的item用不同的viewholder

    以下直接上代码:

      1 class MyAdapter extends BaseAdapter{
      2 
      3     Context mContext;
      4     LinearLayout linearLayout = null;
      5     LayoutInflater inflater;
      6     TextView tex;
      7     final int VIEW_TYPE = 3;
      8     final int TYPE_1 = 0;
      9     final int TYPE_2 = 1;
     10     final int TYPE_3 = 2;
     11 
     12     //各个布局的控件资源
     13     class viewHolder1{
     14         CheckBox checkBox;
     15         TextView textView;
     16     }
     17     class viewHolder2{
     18         TextView textView;
     19     }
     20     class viewHolder3{
     21         ImageView imageView;
     22         TextView textView;
     23     }
     24 
     25     public MyAdapter(Context context) {
     26         // TODO Auto-generated constructor stub
     27         mContext = context;
     28         inflater = LayoutInflater.from(mContext);
     29     }
     30 
     31     @Override
     32     public int getCount() {
     33         // TODO Auto-generated method stub
     34         return listString.size();
     35     }
     36 
     37     //每个convert view都会调用此方法,获得当前所需要的view样式
     38     @Override
     39     public int getItemViewType(int position) {
     40         // TODO Auto-generated method stub
     41         int p = position%6;
     42         if(p == 0)
     43         return TYPE_1;
     44         else if(p < 3)
     45             return TYPE_2;
     46         else if(p < 6)
     47             return TYPE_3;
     48         else
     49             return TYPE_1;
     50     }
     51     
     52     //返回样式的数量
     53     @Override
     54     public int getViewTypeCount() {
     55         // TODO Auto-generated method stub
     56         return 3;
     57     }
     58 
     59     @Override
     60     public Object getItem(int arg0) {
     61         // TODO Auto-generated method stub
     62         return listString.get(arg0);
     63     }
     64 
     65     @Override
     66     public long getItemId(int position) {
     67         // TODO Auto-generated method stub
     68         return position;
     69     }
     70 
     71     @Override
     72     public View getView(int position, View convertView, ViewGroup parent) {
     73         // TODO Auto-generated method stub
     74         viewHolder1 holder1 = null;
     75         viewHolder2 holder2 = null;
     76         viewHolder3 holder3 = null;
     77         int type = getItemViewType(position);
     78 
     79 
     80     //无convertView,需要new出各个控件
     81     if(convertView == null)
     82     { 
     83         Log.e("convertView = ", " NULL");
     84 
     85     //按当前所需的样式,确定new的布局
     86     switch(type)
     87     {
     88     case TYPE_1:
     89     convertView = inflater.inflate(R.layout.listitem1, parent, false);
     90     holder1 = new viewHolder1();
     91     holder1.textView = (TextView)convertView.findViewById(R.id.textview1);
     92     holder1.checkBox = (CheckBox)convertView.findViewById(R.id.checkbox);
     93     Log.e("convertView = ", "NULL TYPE_1");
     94     convertView.setTag(holder1);
     95     break;
     96     case TYPE_2:
     97     convertView = inflater.inflate(R.layout.listitem2, parent, false);
     98     holder2 = new viewHolder2();
     99     holder2.textView = (TextView)convertView.findViewById(R.id.textview2);
    100     Log.e("convertView = ", "NULL TYPE_2");
    101     convertView.setTag(holder2);
    102     break;
    103     case TYPE_3:
    104     convertView = inflater.inflate(R.layout.listitem3, parent, false);
    105     holder3 = new viewHolder3();
    106     holder3.textView = (TextView)convertView.findViewById(R.id.textview3);
    107     holder3.imageView =     (ImageView)convertView.findViewById(R.id.imageview);
    108     Log.e("convertView = ", "NULL TYPE_3");
    109     convertView.setTag(holder3);
    110     break;
    111     }
    112     }
    113     else
    114     {
    115     //有convertView,按样式,取得不用的布局
    116     switch(type)
    117     {
    118     case TYPE_1:
    119     holder1 = (viewHolder1) convertView.getTag();
    120     Log.e("convertView !!!!!!= ", "NULL TYPE_1");
    121     break;
    122     case TYPE_2:
    123     holder2 = (viewHolder2) convertView.getTag();
    124     Log.e("convertView !!!!!!= ", "NULL TYPE_2");
    125     break;
    126     case TYPE_3:
    127     holder3 = (viewHolder3) convertView.getTag();
    128     Log.e("convertView !!!!!!= ", "NULL TYPE_3");
    129     break;
    130     }
    131     }
    132 
    133     //设置资源
    134     switch(type)
    135     {
    136     case TYPE_1:
    137     holder1.textView.setText(Integer.toString(position));
    138     holder1.checkBox.setChecked(true);
    139     break;
    140     case TYPE_2:
    141     holder2.textView.setText(Integer.toString(position));
    142     break;
    143     case TYPE_3:
    144     holder3.textView.setText(Integer.toString(position));
    145     holder3.imageView.setBackgroundResource(R.drawable.icon);
    146     break;
    147     }
    148 
    149 
    150     return convertView;
    151     }
    152 
    153 }    


    参考原文:listview加载性能优化ViewHolder

    参考原文:listView中多个listItem布局时,convertView缓存及使用

  • 相关阅读:
    Django中DEBUG模式详解
    Nginx 的负载均衡
    django 上线配置
    vue 项目实现打印
    vue 一键复制,vue-clipboard2的使用方法
    404.vue
    vue-router封装和用户是否需要登录
    uni-app uview 的使用方法
    grid自适应列表
    tomcat的目录分别代表什么含义
  • 原文地址:https://www.cnblogs.com/tanghuian/p/4585120.html
Copyright © 2011-2022 走看看