广告
返回顶部
首页 > 资讯 > 精选 >Android中怎么实现图片缓存机制
  • 458
分享到

Android中怎么实现图片缓存机制

android 2023-05-30 22:05:38 458人浏览 安东尼
摘要

这期内容当中小编将会给大家带来有关Android中怎么实现图片缓存机制,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Android 图片缓存机制的深入理解Android加载一张图片到用户界面是很简单的,但

这期内容当中小编将会给大家带来有关Android中怎么实现图片缓存机制,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Android 图片缓存机制的深入理解

Android加载一张图片到用户界面是很简单的,但是当一次加载多张图片时,情况就变得复杂起来。很多情况下(像ListView、GridView或ViewPager等组件),屏幕上已显示的图片和即将滑动到当前屏幕上的图片数量基本上是没有限制的。

这些组件通过重用已经移除屏幕的子视图来将降低内存的使用,垃圾回收器也会及时释放那些已经不再使用的已下载的图片,这些都是很好的方法,但是为了保持一个流畅的、快速加载的用户界面,就应该避免当再次回到某个页面时而重新处理图片。内存缓存和磁盘缓存可以帮我们做到这些,它们允许组件快速地重新加载已处理好的图片。

使用内存缓存

内存缓存允许快速地访问图片,但它以占用App宝贵的内存为代价。LruCache类(api Level 4的Support Library也支持)特别适合来做图片缓存,它使用一个强引用的LinkedHashMap来保存最近使用的对象,并且会在缓存数量超出预设的大小之前移除最近最少使用的对象。

说明:以前流行的内存缓存方案是使用软引用或弱引用来缓存图片,然而现在不推荐这样做了,因为从android 2.3(API Level 9)起,垃圾收集器更倾向于先回收软引用或弱引用,这样就使它们变得低效。另外在Android 3.0(API Level 11)之前,图片的像素数据是存储在本地内存(native memory)中的,它以一种不可预测的方式释放,因此可能会导致App超过内存限制甚至崩溃。

为了给LruCache设置一个合适的大小,以下是应该考虑的一些因素:

你的Activity或App的可用内存是多少?

一次展示到屏幕上的图片是多少?有多少图片需要预先准备好以便随时加载到屏幕?

设备的屏幕尺寸和密度是多少?像Galaxy Nexus这样的高分辨率(xhdpi)设备比Nexus S这样分辨率(hdpi)的设备在缓存相同数量的图片时需要更大的缓存空间。

图片的尺寸和配置是怎样的?每张图片会占用多少内存?

图片的访问频率如何?是否有一些图片比另一些访问更加频繁?如果这样的话,或许可以将某些图片一直保存在内存里或者针对不同的图片分组设置不同的LruCache对象。

你能否平衡图片质量和数量之间的关系?有时候存储更多低质量的图片更加有用,当在需要的时候,再通过后台任务下载高质量的图片。

这里没有一个具体的大小和计算公式适用于所有的App,你需要分析你的使用情况并得到一个合适的方案。当一个缓存太小时会导致无益的额外的开销,而缓存太大时也可能会引起Java.lang.OutOfMemory异常,另外缓存越大,留给App其他部分的内存相应就越小。

这里是一个为图片设置LruCache的示例:

private LruCache<String, Bitmap> mMemoryCache;  @Override protected void onCreate(Bundle savedInstanceState) {   ...   // Get max available VM memory, exceeding this amount will throw an   // OutOfMemory exception. Stored in kilobytes as LruCache takes an   // int in its constructor.   final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);    // Use 1/8th of the available memory for this memory cache.   final int cacheSize = maxMemory / 8;    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {     @Override     protected int sizeOf(String key, Bitmap bitmap) {       // The cache size will be measured in kilobytes rather than       // number of items.       return bitmap.getByteCount() / 1024;     }   };   ... }  public void addBitmapToMemoryCache(String key, Bitmap bitmap) {   if (getBitmapFromMemCache(key) == null) {     mMemoryCache.put(key, bitmap);   } }  public Bitmap getBitmapFromMemCache(String key) {   return mMemoryCache.get(key); }

说明:在上述例子中,我们分配了应用内存的1/8作为缓存大小,在一个nORMal/hdpi的设备上最少也有4MB(32/8)的大小。一个800*480分辨率的屏幕上的一个填满图片的GridView大概占用1.5MB(800*480*4byte)的内存,因此该Cache至少可以缓存2.5页这样的图片。

当加载一张图片到ImageView时,首先检查LruCache,如果找到图片,就直接用来更新ImageView,如果没找到就开启一个后台线程来处理:

public void loadBitmap(int resId, ImageView imageView) {   final String imageKey = String.valueOf(resId);    final Bitmap bitmap = getBitmapFromMemCache(imageKey);   if (bitmap != null) {     mImageView.setImageBitmap(bitmap);   } else {     mImageView.setImageResource(R.drawable.image_placeholder);     BitmapWorkerTask task = new BitmapWorkerTask(mImageView);     task.execute(resId);   } }

上述线程中,在解码图片之后,也需要把它添加到内存缓存中:

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {   ...   // Decode image in background.   @Override   protected Bitmap doInBackground(Integer... params) {     final Bitmap bitmap = decodeSampledBitmapFromResource(         getResources(), params[0], 100, 100));     addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);     return bitmap;   }   ... }

使用磁盘缓存

虽然内存缓存在快速访问最近使用的图片时是很有用的,但是你无法保证你所需要的图片就在缓存中,类似GridView这样展示大量数据的组件可以很轻易地就占满内存缓存。你的App也可能被类似电话这样的任务打断,当App被切换到后台后也可能被杀死,内存缓存也可能被销毁,一旦用户回到之前的界面,你的App依然要重新处理每个图片。

磁盘缓存可以用来辅助存储处理过的图片,当内存缓存中图片不可用时,可以从磁盘缓存中查找,从而减少加载次数。当然,从磁盘读取图片要比从内存读取慢并且读取时间是不可预期的,因此需要使用后台线程来读取。

说明:ContentProvider 可能是一个合适的存储频繁访问的图片的地方,比如在Image Gallery应用中。

这里的示例代码是从Android源代码中剥离出来的DiskLruCache,以下是更新后的实例代码,在内存缓存的基础上增加了磁盘缓存:

private DiskLruCache mDiskLruCache; private final Object mDiskCacheLock = new Object(); private boolean mDiskCacheStarting = true; private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB private static final String DISK_CACHE_SUBDIR = "thumbnails";  @Override protected void onCreate(Bundle savedInstanceState) {   ...   // Initialize memory cache   ...   // Initialize disk cache on background thread   File cacheDir = getDiskCacheDir(this, DISK_CACHE_SUBDIR);   new InitDiskCacheTask().execute(cacheDir);   ... }  class InitDiskCacheTask extends AsyncTask<File, Void, Void> {   @Override   protected Void doInBackground(File... params) {     synchronized (mDiskCacheLock) {       File cacheDir = params[0];       mDiskLruCache = DiskLruCache.open(cacheDir, DISK_CACHE_SIZE);       mDiskCacheStarting = false; // Finished initialization       mDiskCacheLock.notifyAll(); // Wake any waiting threads     }     return null;   } }  class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {   ...   // Decode image in background.   @Override   protected Bitmap doInBackground(Integer... params) {     final String imageKey = String.valueOf(params[0]);      // Check disk cache in background thread     Bitmap bitmap = getBitmapFromDiskCache(imageKey);      if (bitmap == null) { // Not found in disk cache       // Process as normal       final Bitmap bitmap = decodeSampledBitmapFromResource(           getResources(), params[0], 100, 100));     }      // Add final bitmap to caches     addBitmapToCache(imageKey, bitmap);      return bitmap;   }   ... }  public void addBitmapToCache(String key, Bitmap bitmap) {   // Add to memory cache as before   if (getBitmapFromMemCache(key) == null) {     mMemoryCache.put(key, bitmap);   }    // Also add to disk cache   synchronized (mDiskCacheLock) {     if (mDiskLruCache != null && mDiskLruCache.get(key) == null) {       mDiskLruCache.put(key, bitmap);     }   } }  public Bitmap getBitmapFromDiskCache(String key) {   synchronized (mDiskCacheLock) {     // Wait while disk cache is started from background thread     while (mDiskCacheStarting) {       try {         mDiskCacheLock.wait();       } catch (InterruptedException e) {}     }     if (mDiskLruCache != null) {       return mDiskLruCache.get(key);     }   }   return null; }  // Creates a unique subdirectory of the designated app cache directory. Tries to use external // but if not mounted, falls back on internal storage. public static File getDiskCacheDir(Context context, String uniqueName) {   // Check if media is mounted or storage is built-in, if so, try and use external cache dir   // otherwise use internal cache dir   final String cachePath =       Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||           !isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() :               context.getCacheDir().getPath();    return new File(cachePath + File.separator + uniqueName); }

上述就是小编为大家分享的Android中怎么实现图片缓存机制了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网精选频道。

--结束END--

本文标题: Android中怎么实现图片缓存机制

本文链接: https://www.lsjlt.com/news/221575.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android中怎么实现图片缓存机制
    这期内容当中小编将会给大家带来有关Android中怎么实现图片缓存机制,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Android 图片缓存机制的深入理解Android加载一张图片到用户界面是很简单的,但...
    99+
    2023-05-30
    android
  • Android中图片的三级缓存机制
    我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制。 原理:   首先根据图片的网络地址在网络上...
    99+
    2022-06-06
    三级缓存 图片 缓存 Android
  • Android 图片的三级缓存机制实例分析
    Android 图片的三级缓存机制实例分析当我们获取图片的时候,如果不加以协调好图片的缓存,就会造成大流量,费流量应用,用户体验不好,影响后期发展。为此,我特地分享Android图片的三级缓存机制之从网络中获取图片,来优化应用,具体分三步进...
    99+
    2023-05-31
    android 图片 三级缓存
  • Android中Glide加载图片并实现图片缓存
    今天工作中遇到Glide的缓存问题,之前在项目中一直用Glide加载本地及网络图片,但是没有考虑过缓存的问题,但是需求中需要提到了,所以在网上查了一下,再这里和大家简单的分享一...
    99+
    2022-06-06
    图片 glide 缓存 Android
  • android实现缓存图片等数据
    采用LinkedHashMap自带的LRU 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的...
    99+
    2022-06-06
    数据 图片 缓存 Android
  • Android使用缓存机制实现文件下载及异步请求图片加三级缓存
    首先给大家介绍Android使用缓存机制实现文件下载 在下载文件或者在线浏览文件时,或者为了保证文件下载的正确性,需要使用缓存机制,常使用SoftReference来实现。 ...
    99+
    2022-06-06
    异步请求 三级缓存 图片 异步 缓存 Android
  • 怎么理解Flutter图片加载与缓存机制
    本篇内容主要讲解“怎么理解Flutter图片加载与缓存机制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解Flutter图片加载与缓存机制”吧!前言今天来学习一下 Flutter 自身是如...
    99+
    2023-06-25
  • PHP中怎么实现缓存机制
    这篇文章给大家介绍PHP中怎么实现缓存机制,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。普遍缓存技术数据缓存:这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不...
    99+
    2023-06-17
  • Android实现图片缓存与异步加载
    ImageManager2这个类具有异步从网络下载图片,从sd读取本地图片,内存缓存,硬盘缓存,图片使用动画渐现等功能,已经将其应用在包含大量图片的应用中一年多,没有出现oom...
    99+
    2022-06-06
    异步加载 图片 异步 缓存 Android
  • Android二级缓存加载图片实现照片墙功能
    实现二级缓存加载图片的功能,在使用DiskLruCache时,需先在工程中添加名为libcore.io的包,并将DiskLruCache.Java文件放进去。DiskLruCache直接百度下载即可。在GridView的适配器中,为Imag...
    99+
    2023-05-31
    android 加载图片 照片墙
  • Java中怎么实现日志缓存机制
    今天就跟大家聊聊有关Java中怎么实现日志缓存机制,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java 日志机制的介绍Java 日志机制在很多文章中都有介绍,为了便于后面文章部分的...
    99+
    2023-06-17
  • Android实现图片异步加载及本地缓存
    在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢...
    99+
    2022-06-06
    异步加载 图片 异步 缓存 Android
  • Android实现图片异步请求加三级缓存
    使用xUtils等框架是很方便,但今天要用代码实现bitmapUtils 的功能,很简单, AsyncTask请求一张图片 ####AsyncTask #####AsyncT...
    99+
    2022-06-06
    异步请求 三级缓存 图片 异步 缓存 Android
  • Android图片三级缓存的原理及其实现
    为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流...
    99+
    2023-05-30
    android 图片 三级缓存
  • redis怎么实现图片流式播放缓存
    要实现图片流式播放缓存,可以使用Redis的List数据结构和Bitmap操作。首先,将图片URL按照顺序加入到Redis的List...
    99+
    2023-09-04
    redis
  • 详解Android中图片的三级缓存及实例
    详解Android中图片的三级缓存及实例为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wi...
    99+
    2023-05-30
    android 三级缓存 roi
  • PHP laravel缓存cache机制怎么实现
    今天小编给大家分享一下PHP laravel缓存cache机制怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧...
    99+
    2023-07-04
  • Android实现图片异步加载并缓存到本地
    在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。 软引用是一个现在非常流行的方法,用户体验比较好...
    99+
    2022-06-06
    异步加载 图片 异步 缓存 Android
  • android怎么实现点击图片切换图片
    在 Android 中,可以通过给 ImageView 添加点击事件来实现点击图片切换图片的功能。下面是一个示例代码:1. 在 XM...
    99+
    2023-08-18
    android
  • java怎么实现Redis的LRU缓存机制
    本篇内容主要讲解“java怎么实现Redis的LRU缓存机制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java怎么实现Redis的LRU缓存机制”吧!目录LRU概述使用LinkedHashM...
    99+
    2023-06-20
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作