私はthquinnのDraggableGridViewを使用しており、そこに〜60枚の画像をロードしています。これはすべてうまくいきます。アセットに必要なすべての画像がありましたが、最初に画像のテキストのみが変更されるため、実行時にそれらを作成したいと考えています。追加は問題になりませんが、アセットからの削除は不可能であり、不要なスペースを使用する Air。ここで私の動機を簡単に説明します。
したがって、この投稿のメソッドを使用してアセット png にテキストを描画し、それをビットマップに変換して LRU キャッシュで使用できるようにしました。これはいくつかの画像で機能しますが、必要なすべての画像を表示しようとするとすぐに OutOfMemory エラーが発生します。ベース画像は 200x200 px で、画面サイズと密度に応じて必要なサイズにスケーリングする必要があると思います。
まず、ビットマップ キャンバスを作成してから、(キャッシュ用に) ビットマップにする LayerdDrawable を作成するため、この方法は効率的ではないようです。確かではありませんが、メモリを乱雑にする多くの一時画像を作成しているように感じます。そして、減価償却された BitmapDrawable を使用しています。BitmapDrawable がないと、このメソッドはどのように見えますか??
私はこれを一般的に正しい方法で行っていますか?また、OOMエラーが発生しないように、このメソッドを効率的に作成するにはどうすればよいですか?!?
ところで。LRUcache を使用せず、GridView の LayerdDrawable を返すだけの場合、画像は正常に読み込まれますが、オリエンテーションを数回変更した後に例外が発生します。これは私が持っている方法です:
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 つしかない場合に、キャッシュされた画像を実際に使用していないようです。
これがフラグメント内にある前に、私も言及できませんでした。それが重要かどうかはわかりません。しかし、縦向きモードではこのフラグメントしかなく、横向きモードでは幅が許せば別のフラグメントが存在する可能性があります。
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;
}
}