美文网首页Android世界Android性能
Android开发系列(2):ListView性能优化1

Android开发系列(2):ListView性能优化1

作者: 梦工厂 | 来源:发表于2015-08-17 14:18 被阅读779次

    一、列表显示三要素:


    1. ListView:用于显示列表的view;
    2. Adapter: 将数据映射到ListView;
    3. Data: 具体的将要被映射的字符串、图片或其他基本组件;

    二、优化原理:


    1. 只创建必要的view对象;
      ListView加载数据的方式: 首先调用getCount()函数,根据返回值得到listView的长度;然后根据这个长度,调用getView()获取listView的每一项item所对应的view。
      如果每一个item都去创建新的对象,必然会占据过多的内存。
    2. 尽可能减少去执行Layout的inflate操作;
      Infalte操作会利用xml文件实例化相应的View,属于IO操作,是耗时操作。
    3. 减少findViewById()操作;
      通过findViewById()方法可以在一个xml文件中寻找view。这个方法会递归整个view树,以寻找与ID相匹配的view。
      当item中含有较复杂的布局时,频繁的回调findViewById()方法无疑会影响滑动的性能。

    三、优化机制:


    1. Recycler(实现原理1和原理2)
      当listView的item离开当前的视图时,对应的view会被缓存在Recycler中。
      这时会相应的从下方生成一个item,而此时调用的getView()函数中的convertView参数就是缓存的view。
      所以listView性能优化的关键在于重用convertView。


      Recycler机制
    2. viewHolder静态类(实现原理3)
      将view的xml中的元素封装成ViewHolder静态类,通过convertView的setTag将view与相应的holder对象绑定在一起。避免大量的findViewById()操作。

    TagsUnlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure.

    (利用tag关联view的额外信息)

    四、优化过程:


    1. 最初写法
    @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
                ImageView imageView1 = (ImageView)view.findViewById(R.id.imageView1);
                TextView textView2 = (TextView)view.findViewById(R.id.text2);
                
                imageView1.setImageResource(R.drawable.ic_launcher);
                textView2.setText(mData.get(position));         
                return view;
            }
    

    (存在问题:1.创建view过多;2.inflate操作过多;3.findViewById()调用次数过多)

    1. 重用convertView
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null){
            convertView = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
        }
        
        ImageView imageView1 = (ImageView)convertView.findViewById(R.id.imageView1);
        TextView textView2 = (TextView)convertView.findViewById(R.id.text2);
        
        imageView1.setImageResource(R.drawable.ic_launcher);
        textView2.setText(mData.get(position)); 
        
        return convertView;
    }
    

    利用Recycler机制,成功解决问题1和问题2;

    1. 利用ViewHolder静态类
    static class ViewHolder{
        ImageView imageView1;
        TextView textView1;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        
        if(convertView == null){
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
            holder.imageView1 = (ImageView)convertView.findViewById(R.id.imageView1);
            holder.textView1 = (TextView)convertView.findViewById(R.id.text1);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        
        holder.imageView1.setImageResource(R.drawable.ic_launcher);
        holder.textView1.setText(mData.get(position));  
        
        return convertView;
    }
    

    利用viewHolder静态类,成功解决问题3;
    (建议将ViewHolder写为静态类,因为用static定义的静态内部类相对独立,不能访问所在类的方法和实体,占用资源更少。如果去掉static,可以彼此互相访问实体,会浪费一些资源。)

    1. 利用依赖注入框架精简代码:
    static class ViewHolder{
            @InjectView(R.id.imageView1)
            ImageView imageView1;
            @InjectView (R.id.text1)
            TextView textView1;
        }
    
    @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            
            if(convertView == null){
                holder = new ViewHolder();
                convertView = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
                convertView.setTag(holder);
            }else{
                holder = (ViewHolder)convertView.getTag();
            }
            
            holder.imageView1.setImageResource(R.drawable.ic_launcher);
            holder.textView1.setText(mData.get(position));  
            
            return convertView;
        }
    

    依赖注入框架能帮你精简应用程序的代码。代码越少意味着出现问题或bug的次数也就越少,从而可以把更多的精力花在项目中那些需要编写或修改的部分,使得阅读代码更加容易。


    [2015-03-18]

    相关文章

      网友评论

        本文标题:Android开发系列(2):ListView性能优化1

        本文链接:https://www.haomeiwen.com/subject/vnnwqttx.html