Reuse重用

来源:互联网 发布:java 字符串和日期比较 编辑:程序博客网 时间:2024/06/11 18:09
Reuse重用,减少内存消耗的重要手段之一。 核心思路就是将已经存在的内存资源重新使用而避免去创建新的,最典型的使用就是缓存(Cache)和池(Pool)。

缓存

Bitmap缓存:    Bitmap缓存分为两种:    一种是内存缓存;    一种是硬盘缓存。内存缓存(LruCache):    以牺牲宝贵的应用内存为代价,内存缓存提供了快速的Bitmap访问方式。系统提供的LruCache类是非常适合用作缓存Bitmap任务的,它将最近被引用到的对象存储在一个强引用的LinkedHashMap中,并且在缓存超过了指定大小之后将最近不常使用的对象释放掉。    注意:以前有一个非常流行的内存缓存实现是SoftReference(软引用)或者WeakReference(弱引用)的Bitmap缓存方案,然而现在已经不推荐使用了。自Android2.3版本(API Level 9)开始,垃圾回收器更着重于对软/弱引用的回收,这使得上述的方案相当无效。硬盘缓存(DiskLruCache):     一个内存缓存对加速访问最近浏览过的Bitmap非常有帮助,但是你不能局限于内存中的可用图片。GridView这样有着更大的数据集的组件可以很轻易消耗掉内存缓存。你的应用有可能在执行其他任务(如打电话)的时候被打断,并且在后台的任务有可能被杀死或者缓存被释放。一旦用户重新聚焦(resume)到你的应用,你得再次处理每一张图片。    在这种情况下,硬盘缓存可以用来存储Bitmap并在图片被内存缓存释放后减小图片加载的时间(次数)。当然,从硬盘加载图片比内存要慢,并且应该在后台线程进行,因为硬盘读取的时间是不可预知的。    注意:如果访问图片的次数非常频繁,那么ContentProvider可能更适合用来存储缓存图片,例如Image Gallery这样的应用程序。    更多关于内存缓存和硬盘缓存的内容请看Google官方教程https://developer.android.com/develop/index.html    图片缓存的开源项目: 对于图片的缓存现在都倾向于使用开源项目,这里我列出几个我搜到的:    1. Android-Universal-Image-Loader 图片缓存    目前使用最广泛的图片缓存,支持主流图片缓存的绝大多数特性。    项目地址:https://github.com/nostra13/Android-Universal-Image-Loader    2. picasso square开源的图片缓存    项目地址:https://github.com/square/picasso    特点:    (1)可以自动检测adapter的重用并取消之前的下载    (2)图片变换    (3)可以加载本地资源    (4)可以设置占位资源    (5)支持debug模式    3. ImageCache 图片缓存,包含内存和Sdcard缓存    项目地址:https://github.com/Trinea/AndroidCommon    特点:    (1)支持预取新图片,支持等待队列    (2)包含二级缓存,可自定义文件名保存规则    (3)可选择多种缓存算法(FIFO、LIFO、LRU、MRU、LFU、MFU等13种)或自定义缓存算法    (4)可方便的保存及初始化恢复数据    (5)支持不同类型网络处理    (6)可根据系统配置初始化缓存等    4. Android 网络通信框架Volley     项目地址:https://android.googlesource.com/platform/frameworks/volley 我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,在2013年的Google I/O发布了Volley。Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮。 特点: (1)JSON,图像等的异步下载; (2)网络请求的排序(scheduling) (3)网络请求的优先级处理 (4)缓存 (5)多级别取消请求 (6)和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)注意: 要根据情况适度使用缓存,因为内存有限。能保存路径地址的就不要存放图片数据,不经常使用的尽量不要缓存,不用时就清空。

对象池:    对象池使用的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。 并非所有对象都适合拿来池化――因为维护对象池也要造成一定开销。对生成时开销不大的对象进行池化,反而可能会出现“维护对象池的开销”大于“生成新对象的开销”,从而使性能降低的情况。但是对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。线程池:    线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。    比如:一个应用要和网络打交道,有很多步骤需要访问网络,为了不阻塞主线程,每个步骤都创建个线程,在线程中和网络交互,用线程池就变的简单,线程池是对线程的一种封装,让线程用起来更加简便,只需要创一个线程池,把这些步骤像任务一样放进线程池,在程序销毁时只要调用线程池的销毁函数即可。

java提供了ExecutorService和Executors类,我们可以应用它去建立线程池。
通常可以建立如下4种:

/** 每次只执行一个任务的线程池 */ExecutorService singleTaskExecutor =          Executors.newSingleThreadExecutor();/** 每次执行限定个数个任务的线程池 */ExecutorService limitedTaskExecutor =         Executors.newFixedThreadPool(3);/** 所有任务都一次性开始的线程池 */ExecutorService allTaskExecutor =         Executors.newCachedThreadPool();/** 创建一个可在指定时间里执行任务的线程池,亦可重复执行 */ExecutorService scheduledTaskExecutor =         Executors.newScheduledThreadPool(3);
0 0
原创粉丝点击