Android中ListView是使用平率最高的控件之一(GridView跟ListView是兄弟,都是继承AbsListView),ListView优化最有效的无非就是采用ViewHolder来减少频繁的对view查询和更新,缓存图片加快解码,减小图片尺寸。
下面是Google的建议
1
2
de >Your code might call findViewById() frequently during the scrolling of ListView, which can slow down perforde>
de >mance. Even when the Adapter returns an inflated view de>de >forde> de >recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the “view holder” design patternde>
说到这里,或许大家有些不耐烦,又是炒冷饭,这个我在09,10年就知道了,不过大家未必就留心了。目前网上优化的大部分教程采用的方法是回调加线程,用handler 交换UI线程和非UI线程的数据(要更新UI,必须要到UI线程里更新,非UI线程更新View会引起一些不比要的bug,Google直接禁用这种方式)。但是留意了下写的不错的(访问量比较高,Google排名靠前),大部分都在回调里还是通过listview的findViewByTag找到对应的ImageView来更新图片。
上面说了,findViewXXX这种方式不大好,对滑动性能有影响。聪明的网友在对listView滑动做了监听,滑动过程中让加载图片的线程阻塞,等到滑动停止了再加载、更新图片。这种方式的确广用,滑动不会觉得卡了,如果用户不细心也看不出啥。这的却很强大,用了锁等机制来进行协作。但是有点小复杂。可能新同事来负责这块,对多线程协作不熟悉,锁容易出bug等。
下面就说说Google在官方文档上的一些经典案例吧。其基本思想就是将网络等耗时操作放到AsyncTask(或线程)中,然后更新UI,为了不影响无用对象回收,将传进来的ImageView以及给ImageView的Bitmap都设为SoftReference,这样不会阻挠虚拟机回收。那如何保证或者如何更新到ImageView上面呢?既然ImageView都回收了,那么这个ImageView肯定不需要贴图了,它逻辑上不应该是显示在现在的位置(ImageView会重用)。教程里用了比较简约(不简单)的处理方式,大家很有必要看看。
教程地址:https://developer.android.com/training/displaying-bitmaps/cache-bitmap.html