关闭

ListView优化方案

标签: javalistview优化内存泄露内存
121人阅读 评论(0) 收藏 举报
分类:

一、复用view

public View getView(int position,View convertView,ViewGroup parent){
    if(convertView == null){
        convertView = LayoutInflater.from(context).inflate(R.layout.section_list_item1,null);
}
    TextViewtv_name = (TextView)convertView.findViewById(R.id.contact_contactinfoitem_tv_name);
    TextViewtv_phone = (TextView)convertView.findViewById(R.id.contact_contactinfoitem_tv_phoneNum);
    ContactInfo1confo=contacts.get(position);
    if(confo != null){
        //toseteveryitem'stext
        tv_name.setText(confo.getContactName());
        tv_phone.setText(confo.getContact_Phone());
    }
    returnconvertView;
}

二、使用viewholder

public View getView(int position,View convertView,ViewGroup parent){
    ViewHolder holder;
    if(convertView == null){
        convertView = LayoutInflater.from(context).inflate(R.layout.section_list_item1,null);
        holder = newViewHolder();
        holder.tv_name = (TextView)convertView.findViewById(R.id.contact_contactinfoitem_tv_name);
        holder.tv_phone = (TextView)convertView.findViewById(R.id.contact_contactinfoitem_tv_phoneNum);
        convertView.setTag(holder);
    }else{
        holder = (ViewHolder)convertView.getTag();
    }
    ContactInfo1 confo = contacts.get(position);
    Log.i("my","confo"+confo.getContactName());
    if(confo! = null){
        //toseteveryitem'stext
        holder.tv_name.setText(confo.getContactName());
        holder.tv_phone.setText(confo.getContact_Phone());
    }
    returnconvertView;
}

class ViewHolder
{
    TextViewtv_name,tv_phone;
}

  并且最好是静态内部类。静态内部类,不持有外部类的引用,避免内存泄露…

  effective Java中有提到过,static class的适用场景,主要作用是为了减少大量内部类都各自持有外部类引用带来的内存开销

  非static内部类会持有外部类的引用,这样就会涉及到外部类的释放依赖内部类。如果内部类过多的引用外部类的话,这样很容易造成外部类得不到释放。

三、listview高度设置成match-parent

四、涉及图片等的时候使用异步加载

  在我的项目中,listview的每一个item都有一个图片和很多TextView,而且所有的TextView都要设置非系统的字体;Adapter使用的是ViewHolder优化,在getView中的代码已经很少了,但是还是卡;我的listview中的数据是一个对象的List,在对象里只存放了item需要展示的图片的资源ID,或者是图片的路径,需要通过一些操作才能获得图片,而这些操作其实是很耗时的;于是我将原来的对象进行了更改,将图片对象直接存放在item对应的对象中,然后再Adapter初始化的时候将这些对象初始化,虽然listview展示所需的时间稍微长了一点,但是结果是listview滑动流畅了很多;接着我又将从assets中获得字体TypeFace的操作放在了Adapter初始化的方法中,并且将字体通过静态的变量都存起来,然后再getView中只需为TextView设置一下taptface即可,不需要在从asset中获取字体所花费的时间;通过上面两步操作之后,我的listview一点都不卡了,十分流畅。
  listview的优化其实就是去找getView中的耗时操作,然后提取出来,要么使用异步的方式为item的布局设置数据,要是实在需要同步,就只能在Adapter初始化时将数据准备好,然后再getView中只需绑定一下就行。

五、异步加载的时候引入线程池和线程队列

  Java中,如果每当一个请求到达就创建一个新线程,开销是相当大的。在实际使用中,每个请求创建新线程的服务器在创建和销 毁线程上花费的时间和消耗的系统资源,甚至可能要比花在处理实际的用户请求的时间和资源要多得多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。
  如果在一个JVM里创建太多的线程,可能会导致系统由于过度消耗内存或“切换过 度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务,这就是“池化资源”技术产生的原因。
  线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。另外,通过适当地调整线程池中的线程数目可以防止出现资源不足的情况。所以,这里我们必须本地维持一个任务队列,将所有需要加载的图片放入队列中,每次只加载当前任务,随着列表的滑动,当前的View显示时,会将该任务置顶,优先加载。这样既能避免过多的线程占用大量资源,又可保证资源的合理使用。

六、listview的多布局

七、listview分页加载

八、对图片进行内存优化

  当程序加载图片的时候,图片的尺寸可能很大,但是在手机上显示的时候,实际在程序中显示的时候,imageview会将大图缩小显示,其实图片中很多细节不会显示出来。但是当我们使用BitmapFactory解析图片的时候,BitmapFactory会将完整的图片解析出来,按照图片的分辨率来创建内存,转换成Bitmap,会占用非常大的内存。

  怎么解决呢?

  在Bitmap加载之前进行设置,降低图片解码后的图片宽高尺寸,以及图像采样率,降低内存占用。可以使用google官方推荐的图片压缩算法。
  图片解码的时候,降低像素颜色信息,从ARGB4字节,转换为Android支持的短字节颜色如ARGB565,去掉透明度。

九、图片的加载引入三级缓存机制

十、图片异步加载引起的错位问题的解决

  因为listview的复用,导致在快速移动的时候,大量调用getview方法,因为复用,导致每一个imageview都可以同时有多个不同网址的异步任务进行加载,这样导致了图片的多次错乱,需要给每一次加载view时的imageview设置tag,这个tag就是网址,在异步任务设置图片的时候,要检查一下,是否当前网址和imageview的tag一致,一致才设置图片。
  因为采用了复用,当listview滚动的时候,实际上显示的是之前加载过的item,之前的item中imageview的内容,就可能是之前其他条目加载的图片信息,这个时候,操作先显示其他条目的图片,之后开启了网络加载后,才会刷新为自身正确的数据。解决方式:在每次getview的时候,都将imageview显示的内容设置为“加载中”图片。覆盖原有旧的数据。

十一、滑动不加载图片停下加载图片

  考虑到实际的人机交互情况,在ListView适配器中,在每一行中都不应该去触发任何异步操作。也就是说,在ListView中有fling(快速滑动)操作时,启动任何异步操作都没有任何意义。一旦滚动停止或即将停止,才是开始真正显示每行的内容的时候。
  当快速滑动列表时(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE 和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来。

具体的实现方式:http://blog.csdn.net/jdsjlzx/article/details/45914707

十二、RecyclerView替代listview的原因

  • RecyclerView封装了viewholder的回收复用。
  • RecyclerView使用布局管理器管理子view的位置(目前尚只提供了LinearLayoutManager),也就是说你再不用拘泥于ListView的线性展示方式(即竖列的展示方式),如果之后提供其他custom LayoutManager的支持,你能够使用复杂的布局来展示一个动态组件。
  • 自带了ItemAnimation,可以设置加载和移除时的动画,方便做出各种动态浏览的效果。

原文链接:http://blog.csdn.net/a910626/article/details/46946639

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6168次
    • 积分:116
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:7篇
    • 译文:0篇
    • 评论:1条
    文章分类
    文章存档
    最新评论