每日一记:Andorid内存和BaseAdapter 的优化

1.Andorid内存与性能优化
今天看到一篇介绍Android内存优化的文章,觉得对于以后的学习很有帮助,决定收藏起来并总结一些知识点。点击查看原文

  • GC 的工作机制
    当 GC 工作时,虚拟机停止其他工作。频繁地触发 GC 进行内存回收,会导致系统性能严重下降。

应该避免GC做不必要的工作。

  • 内存抖动
    在极短的时间内,分配大量的内存,然后又释放它,这种现象就会造成内存抖动。典型地,在 View 控件的 onDraw 方法里分配大量内存,又释放大量内存,这种做法极易引起内存抖动,从而导致性能下降。因为 onDraw 里的大量内存分配和释放会给系统堆空间造成压力,触发 GC 工作去释放更多可用内存,而 GC 工作起来时,又会吃掉宝贵的帧时间 (帧时间是 16ms) ,最终导致性能问题。

  • 内存泄漏
    Java 语言的内存泄漏概念和 C/C++ 不太一样,在 Java 里是指不正确地引用导致某个对象无法被 GC 释放,从而导致可用内存越来越少。比如,一个图片查看程序,使用一个静态 Map 实例来缓存解码出来的 Bitmap 实例来加快加载进度。这个时候就可能存在内存泄漏。内存泄漏会导致可用内存越来越少,从而导致频繁触发 GC 回收内存,进而导致性能下降。

  • 优化内存的几个原则

  • 别在循环里分配内存 (创建新对象)
  • 尽量别在 View 的 onDraw 函数里分配内存(创建新对象)
  • 实在无法避免在这些场景里分配内存时(创建新对象),考虑使用对象池 (Object Pool)

详细的可以见kamidox的Android内存与性能优化

2. ListView 的 BaseAdapter 的优化

  • 因为BaseAdapter是经常使用的,里面的具体方法就略过,只记下最主要的getView()方法

  • 先看这段代码
    public View getView(int position, View convertView, ViewGroup parent) {
    MyInfo userInfo = infos.get(position);
    View view;
    ViewHolder holder; //减少内存中view对象创建的次数
    if (convertView != null && convertView instanceof RelativeLayout) {
    view = convertView;//复用已经回收掉的view对象
    holder = (ViewHolder) view.getTag();//得到他们的引用
    } else {
    view = View.inflate(getApplicationContext(), R.layout.item_layout, null);//把布局文件转化成View对象
    holder = new ViewHolder(); //把ID存到存到holder对象中
    //注意是在view下findViewById
    holder.iv = (ImageView) view.findViewById(R.id.imageView1);
    holder.tv1 = (TextView) view.findViewById(R.id.textView1);
    holder.tv2 = (TextView) view.findViewById(R.id.textView2);
    view.setTag(holder);//对象创建出来时找到他们的引用存到holder中
    }
    holder.tv1.setText(infos.get(position).getName());
    holder.tv2.setText(infos.get(position).getNumber());
    return view;
    }

  • 其中的ViewHolder类如下

    class ViewHolder{
      TextView tv1;
      TextView tv2;
      ImageView iv; 
    }
    
  • getView()方法的参数

    • int position 代表返回的viewListView的第position
    • View convertView 代表了一个从对象池里取出来的view,如果为NULL,说明没有可使用的view,则需要实例化一个,否则可以复用这个view
    • ViewGroup parent 就是这个view的父组件,就是ListView
  • 优化则表现在重复使用已经存在的可复用的view以及保留引用
    getView()方法中,对convertView做判断是否为空值,如果为不为空则拿来重复使用,避免大量实例化view,造成系统资源的浪费,为空则说明对象池中还没有缓存有已经回收的view,则需要实例化。
    那缓存的view是哪里来的?答案就是:ListView显示的itemview的数量一般是固定的,每当上下滑动时,滑动出去显示区域的itemview就会被缓存在对象池中。
    ViewHolder则是相当于一本笔记本的存在,将每个view中的控件引用保留在这个笔记本中,避免每次都要findViewById(),这是相当耗费资源的操作。

你可能感兴趣的:(每日一记:Andorid内存和BaseAdapter 的优化)