android listview 优化

来源:互联网 发布:台湾能独立吗 知乎 编辑:程序博客网 时间:2024/05/24 04:40

在看了一些vogella的文章之后,发现关于android listview性能优化这一段很有意思,于是实践了一下,经过优化,性能确实提升不少!

先看看优化前和优化后的比较:

优化前的log截图:

优化后的log截图:

并且,在不停滚动ListView的过程中,优化之前会出现ANR现象,在AVD上特别容易复现:

然后,优化后显得很流畅,附上对于的log截图:

下面附上相关代码分析:

ListView中的每一个Item由一个ImageView 和一个TextView组成

Layout:

01<?xml version="1.0" encoding="utf-8"?>
02<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03        android:layout_width="fill_parent"
04        android:layout_height="fill_parent"
05        android:orientation="horizontal" >
06         
07        <ImageView android:id="@+id/imageView"
08            android:layout_width="wrap_content"
09            android:layout_height="fill_parent" />"
10        <TextView android:id="@+id/textView"
11            android:layout_width="wrap_content"
12            android:layout_height="fill_parent"
13            android:layout_marginLeft="15dp"
14            android:gravity="center_vertical" />
15</LinearLayout>


Activity继承自ListActivity,我故意增加了Item,方便测试,效果更明显:

01public class ListViewDemo extends ListActivity{
02 
03    private final String[] mItems = new String[] { "Android""iPhone",
04            "WindowsMobile""Blackberry""WebOS""Ubuntu""Windows7",
05            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
06            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2",
07            "Ubuntu""Windows7""Max OS X""Linux""OS/2""Ubuntu",
08            "Windows7""Max OS X""Linux""OS/2""Ubuntu""Windows7",
09            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
10            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2",
11            "Ubuntu""Windows7""Max OS X""Linux""OS/2""Ubuntu",
12            "Windows7""Max OS X""Linux""OS/2""Ubuntu""Windows7",
13            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
14            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2",
15            "Ubuntu""Windows7""Max OS X""Linux""OS/2""Ubuntu",
16            "Windows7""Max OS X""Linux""OS/2""Ubuntu""Windows7",
17            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
18            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2",
19            "Ubuntu""Windows7""Max OS X""Linux""OS/2""Ubuntu",
20            "Windows7""Max OS X""Linux""OS/2""Ubuntu""Windows7",
21            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
22            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2",
23            "Ubuntu""Windows7""Max OS X""Linux""OS/2""Ubuntu",
24            "Windows7""Max OS X""Linux""OS/2""Ubuntu""Windows7",
25            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
26            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2",
27            "Ubuntu""Windows7""Max OS X""Linux""OS/2""Ubuntu",
28            "Windows7""Max OS X""Linux""OS/2""Ubuntu""Windows7",
29            "Max OS X""Linux""OS/2""Ubuntu""Windows7""Max OS X",
30            "Linux""OS/2""Ubuntu""Windows7""Max OS X""Linux""OS/2" };
31    @Override
32    public void onCreate(Bundle savedInstanceState) {
33        super.onCreate(savedInstanceState);
34        ListViewArrayAdapter adapter = new ListViewArrayAdapter(this, mItems);
35        getListView().setAdapter(adapter);
36    }
37}


然后custom Adapter,优化之前的adapter:

01@Override
02    public View getView(int position, View convertView, ViewGroup parent) {
03        long start = System.currentTimeMillis();
04        LayoutInflater inflater = (LayoutInflater) mContext.getLayoutInflater();
05        View rowView = inflater.inflate(mViewResourceId, parent, false);
06        TextView textView = (TextView) rowView
07                .findViewById(mTextViewResourceId);
08        ImageView imageView = (ImageView) rowView
09                .findViewById(mImageViewResourceId);
10        textView.setText(mNames[position]);
11        String s = mNames[position];
12        if (s.startsWith("Windows7") || s.startsWith("iPhone")) {
13            imageView.setImageResource(R.drawable.no);
14        else {
15            imageView.setImageResource(R.drawable.yes);
16        }
17             
18        Log.v("jerikc","cost time = " + (System.currentTimeMillis() - start));
19        return rowView;
20    }


优化之后的Adapter:

01public class ListViewArrayAdapter extends ArrayAdapter<String>{
02 
03    private final Activity mContext;
04    private final String[] mNames;
05    private final static int mViewResourceId = R.layout.text_image_row_layout;
06    private final static int mTextViewResourceId = R.id.textView;
07    private final static int mImageViewResourceId = R.id.imageView;
08    static class ViewHolder {
09        public TextView text;
10        public ImageView image;
11    }
12     
13    public ListViewArrayAdapter(Activity context, String[] names) {
14        super(context, mViewResourceId, names);
15        this.mContext = context;
16        this.mNames = names;
17    }
18     
19    @Override
20    public View getView(int position, View convertView, ViewGroup parent) {
21        long start = System.currentTimeMillis();
22        View rowView = convertView;
23        if (rowView == null) {
24            LayoutInflater inflater = mContext.getLayoutInflater();
25            rowView = inflater.inflate(mViewResourceId, null);
26            ViewHolder viewHolder = new ViewHolder();
27            viewHolder.text = (TextView) rowView.findViewById(mTextViewResourceId);
28            viewHolder.image = (ImageView) rowView.findViewById(mImageViewResourceId);
29            rowView.setTag(viewHolder);
30        }
31         
32        ViewHolder holder = (ViewHolder) rowView.getTag();
33        String s = mNames[position];
34        holder.text.setText(s);
35        if (s.startsWith("Windows7") || s.startsWith("iPhone")) {
36            holder.image.setImageResource(R.drawable.no);
37        else {
38            holder.image.setImageResource(R.drawable.yes);
39        }
40             
41        Log.v("jerikc","cost time = " + (System.currentTimeMillis() - start));
42        return rowView;
43    }
44}


优化的大致思想就是:优化之前,每次加载item的时候,都要加载一下布局文件,然后生成一个新的row View对象,然后通过View找到对应的ImageView和TextView,正如我们所知道的那样,加载布局文件时很耗时的,特别是在操作比较频繁情况下,这是不可忍受的,所以会导致ANR现象。

因此,我们可以重复利用已不可见的row View对象。Android中,当它决定让row View对象不可见的时候,它允许通过getView方法中的convertView参数来重复利用刚刚不可见的row View对象。

在优化的过程中,第一次加载的时候,我们需要把相关的数据保存起来,而View有一个方法setTag,该方法可用来保存一些数据结构。我们一个row View对象是由ImageView和TextView空间组成的,因此定义一个ViewHolder来保存ImageView和TextView对象。在重复利用的过程中,只需简单修改它们的值,而不用再次findViewById

关于findViewById耗时的分析,可参考:

http://www.cnblogs.com/over140/archive/2011/03/23/1991100.html

原创粉丝点击