android ListView性能优化之路 -- 初级

这是一个典型的ListView,当然,不是那种demo级的简单布局。

优化初级:系统机制级优化

界面缓存机制:不管是ios,还是android,都要考虑到巨型数据的情况,比如ListView的Item过万的情况,然后不管一个itemview的布局有多简单,这个界面的内存将巨大无比,即使内存能到较快速的释放,当列表快速滑动的时候,也将巨卡无比,怎么样更少的使用内存,更快的界面绘制,这个是系统级的事情,当然这是google要考虑的:界面缓存。

    /** 系统请求ItemView**/
    @Override   
    public View getView(int position, View convertView, ViewGroup parent) {
        
        /** 
         * 如果系统有缓存,则使用,否则才创建
         * 这个缓存是你用过的,不在使用中的ItemView
         * 例如正在显示第3到9个Item,可能第8个就是第1个Item,第9个复用第2的Item,即将出去的第3被即将进来的第10复用
         **/  
        if (convertView == null) {
            ListViewItemFor2Lines listViewItemFor2Text = new ListViewItemFor2Lines();    
            convertView = listViewItemFor2Text;
        }
                
        return convertView;
    }    

这个缓存是不彻底的,当你使用了上一个缓存的界面时候,你怎么去使用它子view? 于是有一种官方推荐的做法:ViewHolder,子view持有(缓存)

    @Override   
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder  holder = null;
        if (convertView == null) {
            ListViewItemFor2Lines listViewItemFor2Text = new ListViewItemFor2Lines();    
            holder = new ViewHolder();
            holder.view1 = (View)listViewItemFor2Text.findViewById(R.id.view1);
            holder.view2 = (View)listViewItemFor2Text.findViewById(R.id.view2);
            holder.view3 = (View)listViewItemFor2Text.findViewById(R.id.view3);
            //...
            listViewItemFor2Text.setTag(holder);
            convertView = listViewItemFor2Text;
        }
        holder =  (ViewHolder )convertView.getTag();
        //holder.view1.set....
        //holder.view2.set....
        //holder.view2.set....
        //...

        return convertView;
    }   

    public class ViewHolder {
        public int position;    
        public View view1;
        public View view2;
        public View view3;
        //...
    }

到这里,就基本是一个合格的使用者了,但是这够了吗?

认真看第1和第2个Item,其实他们在Layout上是不一样的,复用性不是很强,因为需要重新Layout,我们追求的最极致是什么,就是只要填数据,其他什么都不要做。

系统还准备了一套模板缓存机制。即,可以有多个模板,你要什么模板就直接使用相应的模板。

        /**
         * 各种ItemView的模板总数
         */
        @Override
        public int getViewTypeCount() {
            return ITEMTYPE_COUNT;
        }
        /**
         * 当前ItemView的模板类型
         */
        @Override
        public int getItemViewType(int position) {
            return ITEMTYPE_TYPE;
        }

当要显示一个ItemView的时候,系统会询问,这个Item是什么模板,拿到类型以后在缓存里面找相应的模板,找到了就返回复用,找不到就返回空,找不到的时候你所创建的新模板将标志为系统拿到的模板类型,等待下次返回复用。这时候你要做的就是要在getViewTypeCount清算模板数量,在getItemViewType返回相应的模板类型。

到这里,初级之路已走完,也不容易,走到这里,基本实用了。

posted on 2013-06-07 20:45  asi24  阅读(416)  评论(0编辑  收藏  举报