背景
我的应用中有RecyclerView
(使用GridLayoutManager),需要显示本地存储的一些敏感加密图像。
我不能使用这样的东西,
Glide.with(this).load(encryptedImageFile).into(imageView);
因为我首先需要解密它们然后设置图像。
我做了什么
我有一个AsyncTask解密这些小缩略图,并在ImageView中设置了一个结果Bitmap。
以下是Adapter和AsyncTask的一些小代码片段。
@Override
public void onBindViewHolder(MediaViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
EncryptedFileContainer encryptedFileContainer = getItem(position);
if (encryptedFileContainer != null) {
EncryptedFileDBModel encryptedFileDBModel = encryptedFileContainer.getEncryptedFileDBModel();
holder.mImage.setTag(encryptedFileDBModel.getOriginalFileName());
new BindEncryptedThumbnail(holder, encryptedFileContainer).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
AsyncTask解密并将Bitmaps设置为ImageViews,
static class BindEncryptedThumbnail extends AsyncTask<Object, Void, Bitmap> {
private EncryptedFileContainer mEncryptedFileContainer;
private MediaViewHolder mHolder;
public BindEncryptedThumbnail(MediaViewHolder viewHolder, EncryptedFileContainer encryptedFileContainer) {
this.mHolder = viewHolder;
this.mEncryptedFileContainer = encryptedFileContainer;
}
protected Bitmap doInBackground(Object... objects) {
if (mEncryptedFileContainer.getEncryptedFile() != null) {
return mEncryptedFileContainer.getDecryptedThumb().getThumb(100);
} else {
return null;
}
}
protected void onPostExecute(Bitmap thumbnail) {
String name = (String) mHolder.mImage.getTag();
EncryptedFile encryptedFile = mEncryptedFileContainer.getEncryptedFile();
EncryptedFileDBModel encryptedFileDBModel = mEncryptedFileContainer.getEncryptedFileDBModel();
if (encryptedFile != null && StringUtils.equals(name, encryptedFileDBModel.getOriginalFileName())
&& (thumbnail != null) && (mHolder.mImage != null)) {
mHolder.mImage.setImageBitmap(thumbnail);
} else {
mHolder.mImage.setImageDrawable(ResourceUtils.getDrawable(R.drawable.img_placeholder));
}
}
}
问题
一切正常,图像正确解密并正确设置在RecyclerView项目中。但当有很多图像时,应用程序的内存占用量很高,并且有几个GC ,因为没有BitmapPool可以有效地加载图像。
我不想自己实现磁盘缓存和BitmapPool,因为这些已在Glide中有效完成( FYI,我在我的应用程序的其他部分使用Glide )。
我想使用Glide加载一个Bitmap(由我的AsyncTask返回)并将其设置为ImageView ,以便我可以解密我的图像并利用Glide提供的所有优点。
修改:
添加有关我如何生成缩略图的更多信息。
public Bitmap getThumb(int thumbnailSize) {
if ((!mThumbnailCreated) && (mThumbnailBitmap == null)) {
CipherInputStream streamThumb = readStream();
this.mThumbnailBitmap = ThumbnailEncryptionFactory
.getThumbnailfromStream(streamThumb, thumbnailSize);
}
return mThumbnailBitmap;
}
这个,
public static Bitmap getThumbnailfromStream(CipherInputStream streamThumb, int size) {
if (streamThumb != null) {
try {
byte[] bytes = IOUtils.toByteArray(streamThumb);
return decodeSampledBitmapFromByte(bytes, size, size);
} catch (IOException e) {
Timber.d("Error decoding thumbnail.");
}
}
return null;
}
public static Bitmap decodeSampledBitmapFromByte(byte[] stream, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(stream, 0, stream.length, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(stream, 0, stream.length, options);
}