Android图片压缩及内存缓存
16lz
2022-03-12
Android图片压缩
图片BitmapFactory压缩
Android中提供的对图像的解析BitmapFactory类。直接上代码,以作为记录.
/** * 根据普通需要显示的宽和高进行压缩 * * @param path * @param width * @param height * @return */ protected Bitmap decodeSampledBitmapFromPath(String path, int width, int height) { // 获取图片的宽和高,并不把图片加载到内存当中 BitmapFactory.Options options = new BitmapFactory.Options(); // true表示禁止系统加载图像到内存 options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); options.inSampleSize = caculateInSampleSize(options, width, height); // 使用获取到的inSampleSize再次解析图片 options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(path, options); return bitmap; } /** * 根据需求的宽和高以及实际的宽和高计算SampleSize * * @param options * @param width * @param height * @return */ private int caculateInSampleSize(Options options, int reqWidth, int reqHeight) { int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; // 得到一个比例 if (width > reqWidth || height > reqHeight) { int widthRadio = Math.round(width * 1.0f / reqWidth); int heightRadio = Math.round(height * 1.0f / reqHeight); inSampleSize = Math.max(widthRadio, heightRadio); } return inSampleSize; }
图片缓存LruCache
在过去,我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。下面是使用LruCache的例子
private LruCache<String, Bitmap> mMemoryCache; @Override protected void onCreate(Bundle savedInstanceState) { // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。 // LruCache通过构造函数传入缓存值,以KB为单位。 int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // 使用最大可用内存值的1/8作为缓存的大小。 int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // 重写此方法来衡量每张图片的大小,默认返回图片数量。 return value.getRowBytes() * value.getHeight(); } }; } public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); }
在中高配置的手机当中,这大概会有4兆(32/8)的缓存空间。一个全屏幕的 GridView 使用4张 800x480分辨率的图片来填充,则大概会占用1.5兆的空间(800*480*4)。因此,这个缓存大小可以存储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) { imageView.setImageBitmap(bitmap); } else { imageView.setImageResource(R.drawable.image_placeholder); BitmapWorkerTask task = new BitmapWorkerTask(imageView); task.execute(resId); } }
BitmapWorkerTask 还要把新加载的图片的键值对放到缓存中。
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { // 在后台加载图片。 @Override protected Bitmap doInBackground(Integer... params) { final Bitmap bitmap = decodeSampledBitmapFromResource( getResources(), params[0], 100, 100); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } }
图片的压缩及内存缓存这样的方案,在实战中经常使用到,而且OOM问题有效的得到解决。
更多相关文章
- Android(安卓)Studio的.gitignore以及gitignore无效的解决
- 「抄底 Android(安卓)内存优化 3」 —— JVM 内存管理
- Android清除本地数据缓存代码案例
- Android(安卓)调用相册 拍照 实现系统控件缩放 切割图片
- 短视频app开源源码android 给图片加文字、图片水印
- Android中向服务器上传图片
- Android:如何显示网络图片
- Android(安卓)图片设置圆角
- android背景选择器selector用法汇总