我正在使用thquinn 的 DraggableGridView并将大约 60 个图像加载到其中。这一切都很好。我拥有资产中所需的所有图像,但想在运行时创建它们,因为首先只有图像上的文本会发生变化,这似乎是多余的,我可以减少应用程序大小,第二个原因是我有时需要更改图标添加不会成为问题但无法从资产中删除的空气,并且会占用不必要的空间。在这里简要解释一下我的动机。
所以我使用这篇文章中的方法在我的资产 png 上绘制文本,然后将其转换为位图,以便能够在 LRUcache 中使用它们。这适用于一些图像,但一旦我尝试显示所有需要的图像,我就会收到 OutOfMemory 错误。基本图像是 200x200 像素,我认为也应该根据屏幕尺寸和密度缩放到需要的尺寸。
首先,这种方法似乎效率不高,因为我创建了一个位图画布,然后制作了一个 LayerdDrawable,我再次将其制成位图(用于缓存)。不确定,但感觉就像我正在创建很多临时图像,这会使内存变得混乱。然后我使用了一个折旧的 BitmapDrawable。如果没有 BitmapDrawable,这个方法会怎样?
一般来说,我是否以正确的方式进行此操作,如何有效地使用此方法,以免出现 OOM 错误?!?
顺便提一句。当我不使用 LRUcache 并且只为 GridView 返回 LayerdDrawable 时,图像加载正常,但是在几个方向更改后我得到了异常!这是我在atm拥有的方法:
private Bitmap createIcon(Drawable backgroundImage, String text,
int width, int height) {
String key = text.toLowerCase();
Bitmap cachedBitmap = getBitmapFromMemCache(key);
if (cachedBitmap != null){
Log.d("TRACE", "is cached");
return cachedBitmap;
}
else{
Bitmap canvasBitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
Canvas imageCanvas = new Canvas(canvasBitmap);
Typeface font = Typeface.createFromAsset(getActivity().getAssets(), "myriadpro.ttf");
Paint imagePaint = new Paint();
imagePaint.setTextAlign(Paint.Align.CENTER);
imagePaint.setTextSize(26);//
imagePaint.setTypeface(font);
imagePaint.setAntiAlias(true);
imagePaint.setColor(Color.parseColor("#562b12"));
backgroundImage.draw(imageCanvas);
imageCanvas.drawText(text, (width / 2)+4, (height / 2)-8, imagePaint);
LayerDrawable layerDrawable = new LayerDrawable(
new Drawable[]{backgroundImage, new BitmapDrawable(canvasBitmap)});
int w = layerDrawable.getIntrinsicWidth();
int h = layerDrawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
layerDrawable.draw(canvas);
addBitmapToMemoryCache(key,bitmap);
return bitmap;
}
}
更新: 我现在尝试了另一种方法,这似乎更好,因为它没有使用 BitmapDrawable。但我仍然收到 OOM 错误。此外,它通常似乎并没有真正使用缓存的图像,当我改变方向时,只有 1 或 2 个图像来自缓存。
在 this 在 Fragment 中之前,我也没有提及。不确定是否重要。但是在纵向模式下,我只有这个片段,而在横向模式下,如果宽度允许,可以有另一个片段。
public Bitmap drawTextToBitmap(Context mContext, int resourceId, String mText) {
try {
int memory = (int) (Runtime.getRuntime().freeMemory() / 1024);
Log.d("TRACE", "memory " + memory);
Log.d("TRACE", mText);
String key = mText.toLowerCase();
Bitmap cachedBitmap = getBitmapFromMemCache(key);
if (cachedBitmap != null){
Log.d("TRACE", "is cached");
return cachedBitmap;
}
else{
Resources resources = mContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, resourceId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true); // OOE error happens here
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.rgb(110,110, 110));
paint.setTextSize((int) (25 * scale));
Rect bounds = new Rect();
paint.getTextBounds(mText, 0, mText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/6;
int y = (bitmap.getHeight() + bounds.height())/5;
canvas.drawText(mText, x * scale, y * scale, paint);
addBitmapToMemoryCache(key,bitmap);
return bitmap;
}
} catch (Exception e) {
// TODO: handle exception
return null;
}
}