listview加载性能优化及有多种listitem布局处理方式

来源:互联网 发布:中国人口实时数据 编辑:程序博客网 时间:2024/05/16 06:30

转自:http://www.apkbus.com/forum.php?mod=viewthread&tid=243402

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

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

ListView加载数据都是在

[Java] 纯文本查看 复制代码
?
1
2
3
4
publicView getView(intposition, View convertView, ViewGroup parent) {
   。。。。。。
  
 }

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

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

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

1、最慢的加载方式是每一次都重新定义一个View载入布局,再加载数据
[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
publicView getView(intposition, View convertView, ViewGroup parent) {
     View item = mInflater.inflate(R.layout.list_item_icon_text, null);
 
     ((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
 
     ((ImageView) item.findViewById(R.id.icon)).setImageBitmap((position & 1) == 1? mIcon1 : mIcon2);
 
     returnitem;
 
}

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

[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
publicView getView(intposition, View convertView, ViewGroup parent) {
     if(convertView == null) {
 
         convertView = mInflater.inflate(R.layout.item, parent, false);
 
     }
 
     ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
 
     ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap((position & 1) == 1? mIcon1 : mIcon2);
 
   
     returnconvertView;
 
 }

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

[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
staticclass ViewHolder {
    TextView text;
 
    ImageView icon;
 
}
 
  
 
publicView getView(intposition, View convertView, ViewGroup parent) {
 
    ViewHolder holder;
 
    if(convertView == null) {
 
    convertView = mInflater.inflate(R.layout.list_item_icon_text,parent, false);
 
    holder = newViewHolder();
 
    holder.text = (TextView) convertView.findViewById(R.id.text);
 
    holder.icon = (ImageView) convertView.findViewById(R.id.icon);
 
    convertView.setTag(holder);
 
}else{
 
    holder = (ViewHolder) convertView.getTag();
 
}
 
    holder.text.setText(DATA[position]);
 
    holder.icon.setImageBitmap((position & 1) == 1? mIcon1 :mIcon2);
 
    returnconvertView;
 
}

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

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

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

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

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

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

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

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

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

以下直接上代码:

[Java] 纯文本查看 复制代码
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<font style="color:rgb(51, 51, 51)"><font style="font-size:16px">classMyAdapter extendsBaseAdapter{
 
    Context mContext;
    LinearLayout linearLayout = null;
    LayoutInflater inflater;
    TextView tex;
    finalint VIEW_TYPE = 3;
    finalint TYPE_1 = 0;
    finalint TYPE_2 = 1;
    finalint TYPE_3 = 2;
 
    //各个布局的控件资源
    classviewHolder1{
        CheckBox checkBox;
        TextView textView;
    }
    classviewHolder2{
        TextView textView;
    }
    classviewHolder3{
        ImageView imageView;
        TextView textView;
    }
 
    publicMyAdapter(Context context) {
        // TODO Auto-generated constructor stub
        mContext = context;
        inflater = LayoutInflater.from(mContext);
    }
 
    @Override
    publicint getCount() {
        // TODO Auto-generated method stub
        returnlistString.size();
    }
 
    //每个convert view都会调用此方法,获得当前所需要的view样式
    @Override
    publicint getItemViewType(intposition) {
        // TODO Auto-generated method stub
        intp = position%6;
        if(p == 0)
        returnTYPE_1;
        elseif(p < 3)
            returnTYPE_2;
        elseif(p < 6)
            returnTYPE_3;
        else
            returnTYPE_1;
    }
     
    //返回样式的数量
    @Override
    publicint getViewTypeCount() {
        // TODO Auto-generated method stub
        return3;
    }
 
    @Override
    publicObject getItem(intarg0) {
        // TODO Auto-generated method stub
        returnlistString.get(arg0);
    }
 
    @Override
    publiclong getItemId(intposition) {
        // TODO Auto-generated method stub
        returnposition;
    }
 
    @Override
    publicView getView(intposition, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        viewHolder1 holder1 = null;
        viewHolder2 holder2 = null;
        viewHolder3 holder3 = null;
        inttype = getItemViewType(position);
 
 
    //无convertView,需要new出各个控件
    if(convertView == null)
    {
        Log.e("convertView = "," NULL");
 
    //按当前所需的样式,确定new的布局
    switch(type)
    {
    caseTYPE_1:
    convertView = inflater.inflate(R.layout.listitem1, parent, false);
    holder1 = newviewHolder1();
    holder1.textView = (TextView)convertView.findViewById(R.id.textview1);
    holder1.checkBox = (CheckBox)convertView.findViewById(R.id.checkbox);
    Log.e("convertView = ","NULL TYPE_1");
    convertView.setTag(holder1);
    break;
    caseTYPE_2:
    convertView = inflater.inflate(R.layout.listitem2, parent, false);
    holder2 = newviewHolder2();
    holder2.textView = (TextView)convertView.findViewById(R.id.textview2);
    Log.e("convertView = ","NULL TYPE_2");
    convertView.setTag(holder2);
    break;
    caseTYPE_3:
    convertView = inflater.inflate(R.layout.listitem3, parent, false);
    holder3 = newviewHolder3();
    holder3.textView = (TextView)convertView.findViewById(R.id.textview3);
    holder3.imageView =     (ImageView)convertView.findViewById(R.id.imageview);
    Log.e("convertView = ","NULL TYPE_3");
    convertView.setTag(holder3);
    break;
    }
    }
    else
    {
    //有convertView,按样式,取得不用的布局
    switch(type)
    {
    caseTYPE_1:
    holder1 = (viewHolder1) convertView.getTag();
    Log.e("convertView !!!!!!= ","NULL TYPE_1");
    break;
    caseTYPE_2:
    holder2 = (viewHolder2) convertView.getTag();
    Log.e("convertView !!!!!!= ","NULL TYPE_2");
    break;
    caseTYPE_3:
    holder3 = (viewHolder3) convertView.getTag();
    Log.e("convertView !!!!!!= ","NULL TYPE_3");
    break;
    }
    }
 
    //设置资源
    switch(type)
    {
    caseTYPE_1:
    holder1.textView.setText(Integer.toString(position));
    holder1.checkBox.setChecked(true);
    break;
    caseTYPE_2:
    holder2.textView.setText(Integer.toString(position));
    break;
    caseTYPE_3:
    holder3.textView.setText(Integer.toString(position));
    holder3.imageView.setBackgroundResource(R.drawable.icon);
    break;
    }
 
 
    returnconvertView;
    }
 
}</font></font>

0 0
原创粉丝点击