Android技术积累:图片缓存管理

合集下载

移动应用开发中常见的缓存优化技巧

移动应用开发中常见的缓存优化技巧

移动应用开发中常见的缓存优化技巧在移动应用开发过程中,缓存的使用是提高应用性能和用户体验的关键之一。

合理地使用缓存可以减少网络请求,提高数据加载速度,减轻服务器负载,降低用户流量消耗,以及提升应用的整体响应速度。

本文将介绍一些常见的缓存优化技巧,帮助开发者更好地降低应用的数据耗费和提升应用性能。

1. 内存缓存内存缓存是最快速、最便捷的缓存方式之一。

通过将数据保存到内存中,可以快速地读取数据,避免频繁的网络请求。

Android平台提供了LruCache类,可以在应用程序的内存中实现对象缓存,有效地管理内存资源。

在实际开发中,我们可以将一些频繁使用的数据,如图片、文本等缓存在内存中,提高数据的读取速度。

2. 硬盘缓存和内存缓存相比,硬盘缓存的读写速度较慢,但却可以持久保存数据。

硬盘缓存适用于一些需要较长时间保存的数据,如应用的设置、用户的登录信息等。

Android平台提供了DiskLruCache类,可以将数据缓存到文件系统中,实现数据的长期存储,并提供了数据过期策略,以避免数据的无效使用。

3. 离线缓存离线缓存是一种在网络不稳定或者无网络环境下,提供数据的缓存技术。

通过离线缓存,即使用户处于无网络状态,依然可以正常获取数据。

在设计离线缓存时,可以使用localStorage或IndexedDB等本地存储技术,将数据缓存到本地设备中,并在无网络状态下优先读取本地缓存的数据。

4. 数据预加载数据预加载技术可以在应用启动时,提前加载一些可能会用到的数据。

通过在后台进行数据的预加载,可以提高用户初始页面的加载速度,避免用户长时间等待。

在应用开发中,可以通过不可见的Activity或者Service来进行数据的预加载,提前获取服务器数据,并缓存在设备中,以提高用户体验。

5. 图片缓存图片的加载是移动应用中常见的性能瓶颈之一,过多的网络请求会拖慢应用的速度。

针对这个问题,开发者可以采取图像压缩、延迟加载、图片缓存等策略来优化应用。

Android 平滑图片加载和缓存库 Glide 使用详解

Android 平滑图片加载和缓存库 Glide 使用详解

Android 平滑图片加载和缓存库Glide 使用详解
来源:互联网时间:2015-8-26 8:04:09
本篇文章主要介绍了"Android 平滑图片加载和缓存库Glide 使用详解",主要涉
及到方面的内容,对于Android开发感兴趣的同学可以参考一下:在图片加载库烂大街的今天,选择一个适合自己使用的图片加载库已经成为了每一个Android开发者的必经之路。

现在市面上知名的图片加载库有UIL,Picasso,V...


在图片加载库烂大街的今天,选择一个适合自己使用的图片加载库已经成为了每一个Android开发者的必经之路。

现在市面上知名的图片加载库有UIL,Picass o,Volley ImageLoader,Fresco以及我们今天的主角Glide。

它们各有千秋,不能评定谁一定比谁好,只能说哪一个更适合你。

我的理解
下面我来谈一下个人对这些图片加载库的理解,如有错误,还望指教。

Universal Image Loader:一个强大的图片加载库,包含各种各样的配置,最老牌,使用也最广泛。

Picasso: Square出品,必属精品。

和OkHttp搭配起来更配呦!
Volley ImageLoader:Google官方出品,可惜不能加载本地图片~ Fresco:Facebook出的,天生骄傲!不是一般的强大。

Glide:Google推荐的图片加载库,专注于流畅的滚动。

更多详情请看stackoverflow上这个问题。

android缓存机制原理

android缓存机制原理

android缓存机制原理Android缓存机制原理Android应用的缓存机制为应用带来了很多好处,例如提高应用性能、减小数据流量等等。

下面我们就来深入了解一下Android缓存机制的原理。

1.什么是缓存?在计算机术语中,缓存是指为优化读取操作而预先存储一部分数据的技术。

在Android应用开发中,缓存可以理解为在手机内存或者SD卡中预先存储一些数据,当用户再次访问这个数据的时候,可以直接读取内存中的数据,不必再次通过网络下载。

2. 缓存的类型Android应用的缓存可以分为内存缓存和磁盘缓存两种类型。

内存缓存是指缓存数据存储在内存中,访问速度快,但是容量和生命周期都比较有限。

磁盘缓存则是指缓存数据存储在SD卡或者手机存储空间中,容量大,但是访问速度相对较慢。

3.缓存的原理在Android应用中,缓存的原理可以通过以下四个步骤进行阐述:(1)首先应用会去检查内存缓存,如果内存中有需要用到的数据,则直接从内存中读取数据。

(2)如果内存缓存中没有需要的数据,则应用会去检查磁盘缓存,如果磁盘缓存中有需要用到的数据,则应用会从磁盘中读取数据,同时将数据加载到内存缓存中。

(3)如果内存缓存和磁盘缓存中都没有需要的数据,那么应用会通过网络请求获取数据,同时将获取到的数据写入磁盘缓存和内存缓存中。

(4)应用会设置缓存数据的生命周期,当数据到了需删除的时间段,应用会自动删除这些数据,释放内存和磁盘空间。

4. 如何使用缓存机制在Android应用中,可以通过使用Java语言提供的一些类库来实现缓存机制,例如利用LruCache类实现内存缓存、使用DiskLruCache类实现磁盘缓存等等。

在具体实现中,应该根据实际需求以及设备的存储情况来选择使用哪种缓存方式,同时设置缓存数据的生命周期能够提高应用的性能。

总之,Android应用的缓存机制原理可以通过以上几个方面来阐述。

在实际使用缓存机制时,需要考虑数据的大小、类型、存储时间等等各种因素,合理使用缓存能够大大提高应用的性能和用户体验。

android glide缓存原理

android glide缓存原理

android glide缓存原理
Android应用程序需要使用网络上的图片或者本地图片,它是如何快速加载的?答案就是Glide。

Glide是一个快速、高效、占用内存少的图片加载库。

它可以使我们更加快速地加载图片。

那么Glide如何实现图片的加载呢?以及Glide是如何进行图片的缓存呢?下面,我们将从Glide的原理出发,剖析Glide的缓存机制。

一、Glide启动缓存机制
当我们先请求图片时,Glide会先去加载内存缓存,内存缓存是一个弱引用的HashMap,如果之前已经加载过图片,则从缓存中直接获取,否则, Glide会根据ImageView控件的尺寸去找磁盘缓存,如果也没有磁盘缓存,则网络下载图片。

二、Glide实现磁盘缓存
在Glide的缓存机制中,最重要的部分就是磁盘缓存。

它可以使我们的应用程序更快的加载图片,减少用户用户等待。

一般情况下,磁盘缓存会存储网络请求图片的缓存,从而使再次访问时不需要再次网络请求。

Glide的磁盘缓存机制是这样的:
1.首先,将图片数据转换成一个唯一的key值;
2.接着,根据key值获取磁盘缓存,如果有就直接使用;
3.如果没有,就内存中获取bitmap图片,并存储到磁盘中。

以上就是Glide的缓存机制,最大限度地减少了像素加载所用的时间,使用户的体验更加流畅。

总的来说,Glide是一个实现了图片加载和缓存功能的强大库。

最重要的是,它很轻巧,且资源占用少。

所以,它是Android应用程序中不可或缺的库之一。

图片缓存之内存缓存技术LruCache

图片缓存之内存缓存技术LruCache

图片缓存之内存缓存技术LruCache,软引用每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,这个问题曾经让我觉得很烦恼,后来终于得到了解决,那么现在就让我和大家一起分享一下吧。

这篇博文要讲的图片缓存机制,我接触到的有两钟,一种是软引用,另一种是内存缓存技术。

先来看下两者的使用方式,再来作比较。

除了加载图片时要用到缓存处理,还有一个比较重要的步骤要做,就是要先压缩图片。

1、压缩图片至于要压缩到什么状态就要看自己当时的处境了,压缩图片的时候既要达到一个小的值,又不能让其模糊,更不能拉伸图片。

1./**2. * 加载内存卡图片3. */4. BitmapFactory.Options options =new BitmapFactory.Options();5. options.inJustDecodeBounds = true;// 设置了此属性一定要记得将值设置为false6. Bitmap bitmap =null;7. bitmap = BitmapFactory.decodeFile(url, options);8.int be =(int)((options.outHeight > options.outWidth ? options.outHeight / 1509.: options.outWidth / 200));10.if(be <= 0)// 判断200是否超过原始图片高度11. be = 1;// 如果超过,则不进行缩放12. options.inSampleSize = be;13. options.inPreferredConfig = Bitmap.Config.ARGB_4444;14. options.inPurgeable = true;15. options.inInputShareable = true;16. options.inJustDecodeBounds = false;17.try{18. bitmap = BitmapFactory.decodeFile(url, options);19.}catch(OutOfMemoryError e){20.System.gc();21.Log.e(TAG,"OutOfMemoryError");22.}2、软引用:只要有足够的内存,就一直保持对象,直到发现内存吃紧且没有Strong Ref时才回收对象。

Android6.0 显示系统(三) 管理图像缓冲区

Android6.0 显示系统(三) 管理图像缓冲区

Android6.0 显示系统(三)管理图像缓冲区一、BufferQueueCore BufferQueueProducer BufferQueueConsumer上篇博客在Layer的onFirstRef函数中,调用了下面函数,创建了3个对象BufferQueueCore BufferQueueProducer BufferQueueConsumer。

其中BufferCore是核心,把BufferQueueProducer 和BufferQueueConsumer对象连接在一起。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator) {sp<BufferQueueCore> core(new BufferQueueCore(allocator));sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));*outProducer = producer;*outConsumer = consumer;}1.1 生产者和core的联系IGraphicBufferProducer 的大致接口如下,BufferQueueProducer类是接口IGraphicBufferProducer 的实现,使用BufferQueueProducer之前先要调用connect函数,使用结束后调用disconnect断开连接。

Android中Glide加载库的图片缓存配置究极指南

Android中Glide加载库的图片缓存配置究极指南

Android中Glide加载库的图⽚缓存配置究极指南零、选择Glide为什么图⽚加载我⾸先推荐Glide?图⽚加载框架⽤了不少,从afinal框架的afinalBitmap,Xutils的BitmapUtils,⽼牌框架universalImageLoader,著名开源组织square的picasso,google推荐的glide到FaceBook推出的fresco。

这些我前前后后都体验过,那么⾯对这么多的框架,该如何选择呢?下⾯简单分析下我的看法。

afinal和Xuils在github上作者已经停⽌维护了,开源社区最新的框架要属KJFramework,不过这种快速开发框架看似很好⽤,功能也应有尽有,⼩型项⽬也罢,⼤型项⽬我不是很推荐,这样做项⽬的耦合度太⾼,⼀旦出现停⽌维护,⽽新的问题不断增加,没⼈处理就⿇烦了。

在glide和fresco还未出来的时候,当时最⽕的莫过于universalImageLoader和picasso了,当时觉得universalImageLoader配置相对picasso⿇烦,虽然提供了各种配置,但是没有实践过,根本不知道如何配置,还不如都采⽤默认配置,就选择了picasso作为图⽚加载框架,⽤了近⼀年的时间,没有太⼤的问题,且使⽤简单,或许是因为之前的项⽬太过于简单,周期也并不是很长,还有使⽤eclipse开发,⼀个很⼤的问题⼀直都没有暴露出来,换上了最新的Android Studio可以清晰的看到各种性能相关的监控,如cpu还有内存监控,终于知道了之前做的项⽬都那么的卡顿的罪魁祸⾸,picasso加载稍微⼤⼀点的图⽚就特别耗内存,通常⼀个listView或者顶部滑动⼴告栏都含有多张图⽚,这使得做出的页⾯只要含图⽚较多就异常卡顿(之前的时候还把它归结为测试机不好),知道这⼀点后我就有点想把picasso给替换掉,但这⼀次我不能那么粗⼼。

测试了picasso,glide,universalImageLoader,fresco这四个框架,测试内容⼤概有以下⼏项,内存测试,⼤图⽚测试,⼩图⽚测试,本地图⽚,⽹络图⽚当然还结合官⽅⽂档体验其特⾊功能,内存测试中,glide,universalImageLoader,fresco表现都⾮常优秀,picasso这⼀点上实在是太糟糕了,⼩图⽚差别也不是很⼤,稍微⼤点图⽚内存消耗就要⽐其他⾼出⼏倍,这⼀点上证明了我的猜想,picasso不能再⽤了,下⾯⼀项项分析其他框架,在⾼于2M左右⼤图测试中fresco的表现则和picasso ⼀样直接神马都不显⽰,项⽬中要实现⼤图预览功能,这点上是不⾏的,接着看universalImageLoader和glide在这⼏项测试中成绩都很好,到底该如何选择呢?因为我项⽬之前⽤的picasso,glide从⽤法上⼏乎就是另⼀个picasso,从picasso转移到glide相对改动较少,还有⼀点就是这个项⽬是google在维护,我也能给它更多的信任,相⽐较universalImageLoader,glide可以⽀持gif和短视频,后期也需要⽤到,这⾥不得不谈⼀下glide优秀的缓存机制了,glide图⽚缓存默认使⽤RGB565相当于ARGB8888可以节省不少的空间,⽀持与activity,fragment,application⽣命周期的联动,更智能管理图⽚请求当然还有其他的扩展更多可以看?glide介绍?当然,glide的⽅法数量⽐universalImageLoader多了1000多个,遇到64k问题的会⽐较关注这个。

android 缓存原理

android 缓存原理

android 缓存原理
Android缓存原理是指在Android系统中,通过存储数据的方
式来提高应用程序的性能和响应速度的方法。

Android缓存可
以分为内存缓存和磁盘缓存两种类型。

内存缓存是指将数据存储在应用程序的内存中,以便快速访问和读取。

内存缓存使用HashMap或LruCache等数据结构来存
储数据,并通过键值对的方式进行访问。

内存缓存的优点是读取速度快,适用于一些需要频繁访问的数据,如图片、网络请求结果等。

内存缓存的缺点是占用内存资源较大,不适用于大量数据的存储。

磁盘缓存是指将数据存储在设备的磁盘上,以便在应用程序重新启动时可以从磁盘中恢复数据。

磁盘缓存一般使用文件系统来存储数据,通过文件的读取和写入操作来实现。

磁盘缓存的优点是可以长期保存数据,适用于一些需要持久化存储的数据,如数据库、文件等。

磁盘缓存的缺点是读取速度相对较慢,不适用于频繁访问的数据。

在Android开发中,可以通过一些开源库来实现缓存功能,如Glide、Volley等。

这些库提供了方便的接口和方法,可以简
化缓存的实现过程。

开发者需要结合具体的需求和场景来选择合适的缓存方式,以提高应用程序的性能和用户体验。

在使用缓存的同时,需要注意合理管理缓存数据,避免内存泄漏和数据错乱的问题。

移动应用开发中的本地存储与缓存处理方法

移动应用开发中的本地存储与缓存处理方法

移动应用开发中的本地存储与缓存处理方法随着移动应用的普及,用户对于应用的使用体验要求也越来越高。

在移动应用开发中,本地存储与缓存处理是关键的环节之一。

本文将探讨移动应用开发中常用的本地存储与缓存处理方法。

一、本地存储的意义和方法选择本地存储是指将数据保存在移动设备本地,以便在不联网的情况下能够正常使用应用。

在移动应用开发中选择合适的本地存储方法是十分重要的。

1. SQLite数据库SQLite是一种轻量级的关系型数据库,非常适用于移动应用的本地存储。

SQLite数据库具有结构化、高效的特点,可以有效地处理大量的数据。

对于需要频繁进行增删改查操作的应用来说,SQLite是不错的选择。

2. Shared PreferencesShared Preferences是Android平台提供的一种轻量级的本地存储方式。

它以键值对的形式存储数据,并且可以将不同类型的数据进行存储,如字符串、整型、布尔型等。

但是,Shared Preferences适用于存储较小量的简单数据,对于复杂的数据结构不太适用。

二、本地缓存的作用和处理方法本地缓存是指将应用中的某些数据暂时保存在移动设备上,以便在需要时快速获取。

本地缓存的处理对于提升应用性能和用户体验至关重要。

1. 图片缓存在移动应用中,图片是常见的数据类型之一。

为了减少图片的加载时间,我们可以将图片缓存在本地,下次再次加载时直接从本地读取。

常用的图片缓存方法包括SD卡缓存和内存缓存。

SD卡缓存将图片保存在SD卡上,而内存缓存则将图片保存在应用的内存中。

两者结合使用可以更好地提升图片加载速度。

2. 数据缓存对于一些需要频繁访问的数据,我们也可以进行本地缓存来提升应用的响应速度。

可以使用SQLite数据库、文件缓存等方式进行数据的本地缓存。

对于数据的更新和删除,我们需要及时更新本地缓存,以保证数据的一致性。

三、本地存储和缓存的实际应用场景1. 音乐播放器应用在音乐播放器应用中,需要大量存储音乐文件和相关的元数据。

glide缓存策略

glide缓存策略

glide缓存策略
Glide是一款用于Android平台的图片加载库。

为了提高图片的
加载速度和用户体验,我们可以使用Glide的缓存策略,以下是一些
常用的缓存策略:
1.内存缓存:Glide默认会将加载过的图片缓存在内存中,这样
可以避免每次都从网络或本地磁盘重新下载图片。

我们也可以使用
`skipMemoryCache(true)`方法来跳过内存缓存。

2.磁盘缓存:我们可以将图片缓存在本地磁盘中,这样即使应用
被关闭或设备重启,用户仍然可以访问到已经加载过的图片。

Glide提供了多种磁盘缓存策略,例如`DiskCacheStrategy.ALL`表示缓存所有
版本的图片,`DiskCacheStrategy.NONE`表示不缓存任何图片等。

3.网络缓存:我们可以设置图片缓存在网络中一段时间,这样虽
然会影响图片的实时性,但可以减小服务器负担和提高图片加载速度。

Glide提供了`override()`方法来设置图片的大小,从而优化网络缓存。

总之,合理使用Glide缓存策略可以显著提高应用的图片加载速
度和用户体验。

移动应用开发技术数据缓存与清理方法

移动应用开发技术数据缓存与清理方法

移动应用开发技术数据缓存与清理方法随着移动互联网的高速发展,移动应用开发技术越来越成熟。

作为开发者,我们常常需要处理应用中的数据缓存和清理问题。

本文将介绍一些常见的移动应用开发技术数据缓存与清理方法,帮助我们高效地管理数据。

一、数据缓存的重要性数据缓存是移动应用开发中不可或缺的一环。

通过缓存,我们能够提高应用的响应速度、降低网络请求的成本、节省流量消耗等。

因此,合理使用缓存机制是一项重要的开发技术。

1.内存缓存内存缓存是最常见的数据缓存方式之一。

通过将数据存储在内存中,我们可以快速地读取和写入数据。

在Android开发中,可以使用LruCache等内存缓存方案来管理数据。

需要注意的是,内存缓存只能暂时保存数据,当应用被关闭或系统内存不足时,缓存的数据就会丢失。

2.磁盘缓存与内存缓存相比,磁盘缓存可以长期保存数据。

我们可以将数据存储在设备的存储介质上,以备以后使用。

常见的磁盘缓存方案有文件缓存和数据库缓存。

在Android开发中,可以使用SharedPreferences、SQLite等方式来进行数据的磁盘缓存。

二、数据缓存的清理方法尽管数据缓存对于应用的性能和用户体验至关重要,但缓存的数据也会占用设备的存储空间。

为了避免存储空间被缓存数据过多占用,我们需要定期清理缓存。

1.定期清理开发者可以根据应用的需求,制定定期清理缓存的策略。

可以设置一个时间间隔,在此间隔内进行一次缓存清理。

需要注意的是,清理缓存的频率要慎重选择,过频繁的清理会影响应用的响应速度,而过少的清理则会导致存储空间被过多的缓存数据占用。

2.用户手动清理除了定期清理外,我们还可以提供给用户手动清理缓存的选项。

在应用中添加一个清理缓存的入口,让用户根据自己的需求,选择合适的时机进行清理。

这样既能减轻用户的存储压力,又能提升用户对应用的满意度。

三、数据缓存与清理的注意事项在进行数据缓存与清理时,我们还需注意以下几点。

1.缓存数据的有效性缓存数据的有效性非常重要。

【推荐下载】Android图片缓存之初识Glide

【推荐下载】Android图片缓存之初识Glide

Android 图片缓存之初识Glide2016/06/04 0 前言:前面总结学习了图片的使用以及Lru 算法,今天来学习一下比较优秀的图片缓存开源框架。

技术本身就要不断的更迭,从最初的自己使用SoftReference 实现自己的图片缓存,到后来做电商项目自己的实现方案不能满足项目的需求改用Afinal,由于Afinal 不再维护而选择了师出同门的Xutils,中间也接触过别的开源框架比如Picasso,对Picasso 的第一次印象就不太好,初次接触是拿到了公司刚从外包公司接手过来的图片社交类app,对内存占用太大,直接感受就是导致ListView 滑动有那么一点卡顿,老牌的图片缓存框架universalImageLoader 听说过一直没有真正使用过,之前项目都很小,差不多几百万级别的app,一直使用的都是Xutils,最近觉得项目大起来了,万一Xutils 不维护了或者说要求支持的图片格式多起来的时候,可能Xutils 就不是最佳选择了,这也是来学习Gilde 的根本动机吧。

其实本来想着去学习Facebook 的Fresco 图片框架,但是简单的看了一下,需要连同自定义控件一起使用,功能虽然强大,但是对于已经在维护的项目修改成本那可不是一般的高,以后有兴趣在学习吧!图片缓存相关博客地址:Android 图片缓存之Bitmap 详解Android 图片缓存之初识GlideAndroid 图片缓存之Glide 进阶Android 图片缓存之Lru 算法Glide 简介:Glide 是Google 员工的开源项目,Google I/O 上被推荐使用,一个高效、开源、Android 设备上的媒体管理框架,它遵循BSD、MIT 以及Apache 2.0 协议发布。

Glide 具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API 使开发者能够将Glide 应用在几乎任何网络协议栈里。

【推荐下载】Android 文件缓存方法

【推荐下载】Android 文件缓存方法

Android 文件缓存方法2016/02/01 38642 前言我们经常遇到从网络获取图片,为了使图片查看流畅,我们肯定要使用缓存,大部分我们会使用内存缓存,但是android 内存缓存毕竟是有限的,这样的话,我们必须使用文件来缓存部分图片。

思路当我们把一张图片从网络下载成功以后,这个图片会被加入内存缓存和文件缓存,内存缓存来说请参考Android 内存溢出大总结,对于文件缓存来说,这张图片将被以url 的哈希值加cach 后缀名的形式存储在SD 卡上,这样,当下一次再需要同一个url 的图片的时候,就不需要从网络下载了,而是直接通过url 来进行查找。

同时一张图片被访问时,它的最后修改时间将被更新,这样的意义在于:当SD卡空间不足的时候,将会按照最后修改时间来删除40%缓存的图片,确切来说,那些修改时间比较早的图片将会被删除。

package com.ty.highway.highwaysystem.support.utils.cache;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Environment;import android.os.StatFs;import android.util.Log;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.util.Arrays;import parator;/** * Created by fuweiwei on 2016/1/26. * 文件缓存* 内存缓存是有限的,其它的文件缓存,当文件缓存操作一定量时我们删除之前的缓存*/public class ImageFileCache{ private static final String TAG = “ImageFileCache”;//图片缓存目录private static final String IMGCACHDIR = “/sdcard/ImgCach”; //保存的cache 文件宽展名private static final String CACHETAIL = “.cach”; private static final int MB = 1024*1024; private static final int CACHE_SIZE = 1; //当SD 卡剩余空间小于10M 的时候会清理缓存private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10; public ImageFileCache() { //清理部分文件缓存removeCache(IMGCACHDIR); } /** * 从缓存中获取图片*/ public Bitmap。

教你写Android-ImageLoader框架之图片缓存-(完结篇)

教你写Android-ImageLoader框架之图片缓存-(完结篇)

教你写Android ImageLoader框架之图片缓存(完结篇)在教你写Android ImageLoader框架系列博文中,我们从基本架构到具体实现已经更新了大部分的内容。

今天,我们来讲最后一个关键点,即图片的缓存。

为了用户体验,通常情况下我们都会将已经下载的图片缓存起来,一般来说内存和本地都会有图片缓存。

那既然是框架,必然需要有很好的定制性,这让我们又自然而然的想到了抽象。

下面我们就一起来看看缓存的实现吧。

缓存接口在教你写Android ImageLoader框架之图片加载与加载策略我们聊到了Loader,然后阐述了AbsLoader的基本逻辑,其中就有图片缓存。

因此AbsLoader中必然含有缓存对象的引用。

我们看看相关代码:/*** @author mrsimple*/public abstract class AbsLoader implements Loader {/*** 图片缓存*/private static BitmapCache mCache = SimpleImageLoader.getInstance().getConfig().bitmapCache;// 代码省略}23456789101112 AbsLoader中定义了一个static的BitmapCache对象,这个就是图片缓存对象。

那为什么是static呢?因为不管Loader有多少个,缓存对象都应该是共享的,也就是缓存只有一份。

说了那么多,那我们先来了解一下BitmapCache吧。

public interface BitmapCache {public Bitmap get(BitmapRequest key);public void put(BitmapRequest key, Bitmap value);public void remove(BitmapRequest key);}12345679 BitmapCache很简单,只声明了获取、添加、移除三个方法来操作图片缓存。

详解Android图片的三级缓存及图片压缩

详解Android图片的三级缓存及图片压缩

详解Android图⽚的三级缓存及图⽚压缩为什么需要图⽚缓存Android默认给每个应⽤只分配16M的内存,所以如果加载过多的图⽚,为了防⽌内存溢出,应该将图⽚缓存起来。

图⽚的三级缓存分别是:内存缓存本地缓存⽹络缓存其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;⽹络缓存不应该优先加载,它⾛⽹络,速度慢且耗流量。

三级缓存的具体实现⽹络缓存根据图⽚的url去加载图⽚在本地和内存中缓存public class NetCacheUtils {private LocalCacheUtils mLocalCacheUtils;private MemoryCacheUtils mMemoryCacheUtils;public NetCacheUtils(LocalCacheUtils localCacheUtils,MemoryCacheUtils memoryCacheUtils) {mLocalCacheUtils = localCacheUtils;mMemoryCacheUtils = memoryCacheUtils;}/*** 从⽹络下载图⽚** @param ivPic* @param url*/public void getBitmapFromNet(ImageView ivPic, String url) {new BitmapTask().execute(ivPic, url);// 启动AsyncTask,// 参数会在doInbackground中获取}/*** Handler和线程池的封装** 第⼀个泛型: 参数类型第⼆个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果***/class BitmapTask extends AsyncTask<Object, Void, Bitmap> {private ImageView ivPic;private String url;/*** 后台耗时⽅法在此执⾏, ⼦线程*/@Overrideprotected Bitmap doInBackground(Object... params) {ivPic = (ImageView) params[0];url = (String) params[1];ivPic.setTag(url);// 将url和imageview绑定return downloadBitmap(url);}/*** 更新进度, 主线程@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);}/*** 耗时⽅法结束后,执⾏该⽅法, 主线程*/@Overrideprotected void onPostExecute(Bitmap result) {if (result != null) {String bindUrl = (String) ivPic.getTag();if (url.equals(bindUrl)) {// 确保图⽚设定给了正确的imageviewivPic.setImageBitmap(result);mLocalCacheUtils.setBitmapToLocal(url, result);// 将图⽚保存在本地mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图⽚保存在内存System.out.println("从⽹络缓存读取图⽚啦...");}}}}/*** 下载图⽚** @param url* @return*/private Bitmap downloadBitmap(String url) {HttpURLConnection conn = null;try {conn = (HttpURLConnection) new URL(url).openConnection();conn.setConnectTimeout(5000);conn.setReadTimeout(5000);conn.setRequestMethod("GET");conn.connect();int responseCode = conn.getResponseCode();if (responseCode == 200) {InputStream inputStream = conn.getInputStream();//图⽚压缩处理BitmapFactory.Options option = new BitmapFactory.Options();option.inSampleSize = 2;//宽⾼都压缩为原来的⼆分之⼀, 此参数需要根据图⽚要展⽰的⼤⼩来确定 option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图⽚格式Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);return bitmap;}} catch (Exception e) {e.printStackTrace();} finally {conn.disconnect();}return null;}}本地缓存两个⽅法:设置本地缓存,获取本地缓存public class LocalCacheUtils {public static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/local_cache";/*** 从本地sdcard读图⽚public Bitmap getBitmapFromLocal(String url) {try {String fileName = MD5Encoder.encode(url);File file = new File(CACHE_PATH, fileName);if (file.exists()) {Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));return bitmap;}} catch (Exception e) {e.printStackTrace();}return null;}/*** 向sdcard写图⽚** @param url* @param bitmap*/public void setBitmapToLocal(String url, Bitmap bitmap) {try {String fileName = MD5Encoder.encode(url);File file = new File(CACHE_PATH, fileName);File parentFile = file.getParentFile();if (!parentFile.exists()) {// 如果⽂件夹不存在, 创建⽂件夹parentFile.mkdirs();}// 将图⽚保存在本地press(CompressFormat.JPEG, 100,new FileOutputStream(file));} catch (Exception e) {e.printStackTrace();}}}内存缓存两个⽅法:设置内存缓存,获取内存缓存问题:如果使⽤HashMap存储图⽚时,当图⽚越来越多时,会导致内存溢出,因为它是强引⽤,java的垃圾回收器不会回收。

Android图片缓存之Lru算法

Android图片缓存之Lru算法

Android图⽚缓存之Lru算法前⾔:上篇我们总结了Bitmap的处理,同时对⽐了各种处理的效率以及对内存占⽤⼤⼩。

我们得知⼀个应⽤如果使⽤⼤量图⽚就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发⽣的概率呢?之前我们⼀直在使⽤SoftReference软引⽤,SoftReference是⼀种现在已经不再推荐使⽤的⽅式,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引⽤或弱引⽤的对象,这让软引⽤变得不再可靠,所以今天我们来认识⼀种新的缓存处理算法Lru,然后学习⼀下基于Lru的Lrucache、DiskLruCache 实现我们的图⽚缓存。

图⽚缓存相关博客地址:Lru:LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使⽤”,LRU缓存就是使⽤这种原理实现,简单的说就是缓存⼀定量的数据,当超过设定的阈值时就把⼀些过期的数据删除掉,⽐如我们缓存10000条数据,当数据⼩于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最⼤缓存10000条,那怎么确定删除哪条过期数据呢,采⽤LRU算法实现的话就是将最⽼的数据删掉。

基于LruCache实现内存缓存:1.)初始化MemoryCache这⾥内存缓存的是Drawable ⽽不是Bitmap 理由是Drawable相对Bitmap来说有很⼤的内存优势int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取系统分配给应⽤的总内存⼤⼩int mCacheSize = maxMemory / 8;//设置图⽚内存缓存占⽤⼋分之⼀mMemoryCache = new LruCache<String, Drawable>(mCacheSize) {//必须重写此⽅法,来测量Bitmap的⼤⼩@Overrideprotected int sizeOf(String key, Drawable value) {if (value instanceof BitmapDrawable) {Bitmap bitmap = ((BitmapDrawable) value).getBitmap();return bitmap == null ? 0 : bitmap.getByteCount();}return super.sizeOf(key, value);}};2.)添加⼀个Drawable到内存缓存/*** 添加Drawable到内存缓存** @param key* @param drawable*/private void addDrawableToMemoryCache(String key, Drawable drawable) {if (getDrawableFromMemCache(key) == null && drawable != null) {mMemoryCache.put(key, drawable);}}3.)从内存缓存中获取⼀个Drawable/*** 从内存缓存中获取⼀个Drawable** @param key* @return*/public Drawable getDrawableFromMemCache(String key) {return mMemoryCache.get(key);}4.)从内存缓存中移除⼀个Drawable/**** @param key*/public void removeCacheFromMemory(String key) {mMemoryCache.remove(key);}5.)清空内存缓存/*** 清理内存缓存*/public void cleanMemoryCCache() {mMemoryCache.evictAll();}其实Lru缓存机制本质上就是存储在⼀个LinkedHashMap存储,为了保障插⼊的数据顺序,⽅便清理。

简单的图片缓存

简单的图片缓存

简单的图片缓存_V客学院Android技术分享(V客学院android开发小知识)在开发Android项目中,大多数人会接触到异步加载图片或者是加载大量图片等,这其中会牵扯到一个很重要的问题:用户的流量。

假设打开一款APP,而这款APP没有经过图片缓存,那么每次打开APP就会请求一次网络获取图片(注:当然还有其他数据,这里只处理图片),结果一是浪费用户大量的流量,二是在没有网络情况下有图片的布局显示不出图片。

现在一九八网络科技V客学院的android开发大神就介绍了一种简易的图片缓存牵扯到了软引用和本地文件缓存。

何为软引用?从JDK1.2开始,java将对象分成了四种级别,以达到程序对对象生财周期的灵活控制,这四个级别由强到弱是:强引用,软引用,弱引用,虚引用。

强引用就不多说了,就是我们平时直接new出来的一个对象,不做任何的修饰,就是强引用。

虚引用暂未使用过也就没做过深入了解,弱引用的使用方式基本和软引用是一样的,所以就重点看了一下应用程序如何使用软引用。

如果一个对象只具有软引用,那么如果内存如果够用的话,GC 就不会回收它,如果内存不足了,就会优先回收只有软引用的对象内存,而保证不会内存溢出。

基于软引用的这个特性,我们可以使用软引用来实现内存敏感区的高速缓存,因此为了防止内存溢出的发生,在处理一些占用内存较大且声明周期较长的对象的时候,我们可以尽量使用软引用,例如: Context及其子类对象,Drawable及其子类对象,Bitmap位图对象等,在创建这些类的对象的时候,尽量将其声明为软引用。

(以上解析网上转载)。

软引用调用对象声明:SoftReference instance。

本地文件缓存指的是第一次进入APP时将从网上获取下来的图片存在本地,等多次进入APP时先在本地文件缓存文件中判断是否存在,存在即加载本地图片。

以下是本篇代码详细解释。

单独将网络请求主体代码列出来做一个网络请求工具类,作用是代码的优化,多次请求网络时,都需要声明一次网络请求方法,既然如此我们单独列出来做成一个公共调用的工具类。

glide 原理

glide 原理

glide 原理Glide是一款用于Android平台的强大的图片加载和缓存库。

它能够帮助开发者优化图片加载的性能,并提供了简单易用的API供开发使用。

Glide的原理主要包括以下几个方面:1. 请求管理:当开发者使用Glide加载图片时,首先会创建一个图片加载请求对象。

这个请求对象包含了图片的URL或资源ID等信息。

Glide会对这些请求进行管理,并根据需要进行并发或顺序处理。

2. 缓存策略:Glide使用了一套复杂的缓存策略来提高图片加载的性能。

它会根据图片的URL或资源ID生成一个唯一的缓存键,并根据这个键值进行图片的存储、读取和清除等操作。

Glide提供了多级缓存机制,包括内存缓存、磁盘缓存以及外部缓存等,以满足不同的需求。

3. 图片解码和转换:Glide会根据图片的格式和展示需求进行相应的解码和转换操作。

它可以将原始的图片数据转换为适合展示的Bitmap对象,并进行压缩、缩放、裁剪等处理,以减少内存占用和提高展示效果。

4. 生命周期管理:Glide能够与Activity或Fragment等组件的生命周期进行绑定,使得图片加载和显示的过程与组件的生命周期保持一致。

这样可以避免在组件销毁后仍然进行图片加载的情况,提高了内存的利用率和整体的性能。

5. 自定义扩展:Glide提供了丰富的扩展接口和功能,允许开发者根据需要进行自定义的处理。

例如,开发者可以通过自定义的图像变换器,对加载的图片进行特效处理;还可以通过自定义的缓存策略,实现更灵活的缓存管理。

总的来说,Glide的原理是通过合理的请求管理、缓存策略、图片解码和转换、生命周期管理以及自定义扩展等机制,使得图片加载在保证性能的同时,提供了简单易用且功能强大的API供开发者使用。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

如果每次加载同一张图片都要从网络获取,那代价实在太大了。

所以同一张图片只要从网络获取一次就够了,然后在本地缓存起来,之后加载同一张图片时就从缓存中加载就可以了。

从内存缓存读取图片是最快的,但是因为内存容量有限,所以最好再加上文件缓存。

文件缓存空间也不是无限大的,容量越大读取效率越低,因此可以设置一个限定大小比如10M,或者限定保存时间比如一天。

因此,加载图片的流程应该是:1、先从内存缓存中获取,取到则返回,取不到则进行下一步;2、从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行下一步;3、从网络下载图片,并更新到内存缓存和文件缓存。

接下来看内存缓存类:ImageMemoryCache1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132 public class ImageMemoryCache {/*** 从内存读取数据速度是最快的,为了更大限度使用内存,这里使用了两层缓存。

* 硬引用缓存不会轻易被回收,用来保存常用数据,不常用的转入软引用缓存。

*/private static final int SOFT_CACHE_SIZE = 15; //软引用缓存容量private static LruCache<String, Bitmap> mLruCache; //硬引用缓存private static LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache; //软引用缓存public ImageMemoryCache(Context context) {int memClass =((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();int cacheSize = 1024 * 1024 * memClass / 4; //硬引用缓存容量,为系统可用内存的1/4mLruCache = new LruCache<String, Bitmap>(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap value) {if (value != null)return value.getRowBytes() * value.getHeight();elsereturn 0;}@Overrideprotected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {if (oldValue != null)// 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存 mSoftCache.put(key, new SoftReference<Bitmap>(oldValue));}};mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>(SOFT_CACHE_SIZE, 0.75f, true) { private static final long serialVersionUID = 6040103833179403725L;3334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 @Overrideprotected boolean removeEldestEntry(Entry<String, SoftReference<Bitmap>> eldest) {if (size() > SOFT_CACHE_SIZE){return true;}return false;}};}/*** 从缓存中获取图片*/public Bitmap getBitmapFromCache(String url) {Bitmap bitmap;//先从硬引用缓存中获取synchronized (mLruCache) {bitmap = mLruCache.get(url);if (bitmap != null) {//如果找到的话,把元素移到LinkedHashMap的最前面,从而保证在LRU算法中是最后被删除 mLruCache.remove(url);mLruCache.put(url, bitmap);return bitmap;}}//如果硬引用缓存中找不到,到软引用缓存中找synchronized (mSoftCache) {SoftReference<Bitmap> bitmapReference = mSoftCache.get(url);if (bitmapReference != null) {bitmap = bitmapReference.get();if (bitmap != null) {//将图片移回硬缓存mLruCache.put(url, bitmap);mSoftCache.remove(url);return bitmap;} else {mSoftCache.remove(url);}}}return null;}/**777879808182838485868788 * 添加图片到缓存*/public void addBitmapToCache(String url, Bitmap bitmap) { if (bitmap != null) {synchronized (mLruCache) {mLruCache.put(url, bitmap);}}}public void clearCache() {mSoftCache.clear();}}文件缓存类:ImageFileCache1 2 3 4 5 6 7 8 9101112131415161718192021222324252627 public class ImageFileCache {private static final String CACHDIR = "ImgCach";private static final String WHOLESALE_CONV = ".cach";private static final int MB = 1024*1024;private static final int CACHE_SIZE = 10;private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;public ImageFileCache() {//清理文件缓存removeCache(getDirectory());}/** 从缓存中获取图片 **/public Bitmap getImage(final String url) {final String path = getDirectory() + "/" + convertUrlToFileName(url); File file = new File(path);if (file.exists()) {Bitmap bmp = BitmapFactory.decodeFile(path);if (bmp == null) {file.delete();} else {updateFileTime(path);return bmp;}}return null;2829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 }/** 将图片存入文件缓存 **/public void saveBitmap(Bitmap bm, String url) {if (bm == null) {return;}//判断sdcard上的空间if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {//SD空间不足return;}String filename = convertUrlToFileName(url);String dir = getDirectory();File dirFile = new File(dir);if (!dirFile.exists())dirFile.mkdirs();File file = new File(dir +"/" + filename);try {file.createNewFile();OutputStream outStream = new FileOutputStream(file);press(pressFormat.JPEG, 100, outStream); outStream.flush();outStream.close();} catch (FileNotFoundException e) {Log.w("ImageFileCache", "FileNotFoundException");} catch (IOException e) {Log.w("ImageFileCache", "IOException");}}/*** 计算存储目录下的文件大小,* 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定* 那么删除40%最近没有被使用的文件*/private boolean removeCache(String dirPath) {File dir = new File(dirPath);File[] files = dir.listFiles();if (files == null) {return true;}if (!android.os.Environment.getExternalStorageState().equals(72737475767778798081828384858687888990919293949596979899 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 android.os.Environment.MEDIA_MOUNTED)) {return false;}int dirSize = 0;for (int i = 0; i < files.length; i++) {if (files[i].getName().contains(WHOLESALE_CONV)) {dirSize += files[i].length();}}if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) { int removeFactor = (int) ((0.4 * files.length) + 1);Arrays.sort(files, new FileLastModifSort());for (int i = 0; i < removeFactor; i++) {if (files[i].getName().contains(WHOLESALE_CONV)) {files[i].delete();}}}if (freeSpaceOnSd() <= CACHE_SIZE) {return false;}return true;}/** 修改文件的最后修改时间 **/public void updateFileTime(String path) {File file = new File(path);long newModifiedTime = System.currentTimeMillis();file.setLastModified(newModifiedTime);}/** 计算sdcard上的剩余空间 **/private int freeSpaceOnSd() {StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;return (int) sdFreeMB;}/** 将url转成文件名 **/116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 private String convertUrlToFileName(String url) {String[] strs = url.split("/");return strs[strs.length - 1] + WHOLESALE_CONV;}/** 获得缓存目录 **/private String getDirectory() {String dir = getSDPath() + "/" + CACHDIR;return dir;}/** 取SD卡路径 **/private String getSDPath() {File sdDir = null;boolean sdCardExist = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在 if (sdCardExist) {sdDir = Environment.getExternalStorageDirectory(); //获取根目录 }if (sdDir != null) {return sdDir.toString();} else {return "";}}/*** 根据文件的最后修改时间进行排序*/private class FileLastModifSort implements Comparator<File> {public int compare(File arg0, File arg1) {if (stModified() > stModified()) {return 1;} else if (stModified() == stModified()) {return 0;} else {return -1;}}}}从网络获取图片:1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243 public class ImageGetFormHttp {private static final String LOG_TAG = "ImageGetForHttp";public static Bitmap downloadBitmap(String url) {final HttpClient client = new DefaultHttpClient();final HttpGet getRequest = new HttpGet(url);try {HttpResponse response = client.execute(getRequest);final int statusCode = response.getStatusLine().getStatusCode();if (statusCode != HttpStatus.SC_OK) {Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);return null;}final HttpEntity entity = response.getEntity();if (entity != null) {InputStream inputStream = null;try {inputStream = entity.getContent();FilterInputStream fit = new FlushedInputStream(inputStream);return BitmapFactory.decodeStream(fit);} finally {if (inputStream != null) {inputStream.close();inputStream = null;}entity.consumeContent();}}} catch (IOException e) {getRequest.abort();Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);} catch (IllegalStateException e) {getRequest.abort();Log.w(LOG_TAG, "Incorrect URL: " + url);} catch (Exception e) {getRequest.abort();Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);} finally {client.getConnectionManager().shutdown();}4445464748495051525354555657585960616263646566676869707172 return null;}/** An InputStream that skips the exact number of bytes provided, unless it reaches EOF. */static class FlushedInputStream extends FilterInputStream {public FlushedInputStream(InputStream inputStream) {super(inputStream);}@Overridepublic long skip(long n) throws IOException {long totalBytesSkipped = 0L;while (totalBytesSkipped < n) {long bytesSkipped = in.skip(n - totalBytesSkipped);if (bytesSkipped == 0L) {int b = read();if (b < 0) {break; // we reached EOF} else {bytesSkipped = 1; // we read one byte}}totalBytesSkipped += bytesSkipped;}return totalBytesSkipped;}}}最后,获取一张图片的流程就如下代码所示:1 2 3 4 5 6 7 8 91011 /*** 获得一张图片,从三个地方获取,首先是内存缓存,然后是文件缓存,最后从网络获取 ***/public Bitmap getBitmap(String url) {// 从内存缓存中获取图片Bitmap result;result = memoryCache.getBitmapFromCache(url);if (result == null) {// 文件缓存中获取result = fileCache.getImage(url);if (result == null) {// 从网络获取1213141516171819202122 result = ImageGetFormHttp.downloadBitmap(url); if (result != null) {fileCache.saveBitmap(result, url);memoryCache.addBitmapToCache(url, result); }} else {// 添加到内存缓存memoryCache.addBitmapToCache(url, result);}}return result;}。

相关文档
最新文档