最近ライブ壁紙を作りました。2 つの画像を並べて表示します。各画像は画面の半分の幅をとります。画面を移動すると(ホーム画面で横に移動すると)、画像も移動します。
できるだけ見栄えを良くしたかったので、すべての背景画像の解像度は 1320x958です。高さが理想的ではないことはわかっていますが、使用したほとんどの画像から得られた最高の高さでした。
壁紙の開始時に、画像は画面の高さに合わせて拡大縮小され、適切な幅が計算されます。小さいディスプレイ (ldpi、mdpi) のデバイスでは問題なく動作します。
問題は、大画面のデバイスで、画像をアップスケールする (ダウンスケールしない) 必要がある場合、突然java.lang.OutOfMemoryError
. Samsung S3 からクラッシュ レポートを受け取りました。画面が小さい (メモリが少ない) 古いデバイスでは問題が発生しないのに、画面が大きいデバイス (使用可能なメモリが多い) でこれがどのように発生するのかわかりません。
これが私のコードです:
private void InitializeBackgrounds()
{
Resources res = getApplicationContext().getResources();
// Load and scale backgrounds
int bg_height = height;
int bg_width = (int)((float)bg_height/958.0f*1320.0f);
try {
// Load random image from array of images
Bitmap original = BitmapFactory.decodeResource(res, left_files[r.nextInt(left_files.length)]);
// Scale image to new size
spurs = Bitmap.createScaledBitmap(original, bg_width, bg_height, true);
// Free up memory immediately
original.recycle();
// Do the same for right image
original = BitmapFactory.decodeResource(res, right_files[r.nextInt(right_files.length)]);
heat = Bitmap.createScaledBitmap(original, bg_width, bg_height, true);
original.recycle();
}
catch (OutOfMemoryError e){
throw new OutOfMemoryError("OutOfMemoryException;InitializeBackgrounds(); model: " + Build.MODEL + "; LocalizedMessage: "+e.getLocalizedMessage()+"; Message: "+e.getMessage());
}
}
後で描画すると、読み込まれた画像は画面の幅に合わせてトリミングされます。画面を移動すると画像が動く効果があります。そのため、画面よりも大きな画像をメモリにロードしました。
private void drawWallpaper(Canvas c)
{
// ...
try {
bg_left = Bitmap.createBitmap(spurs, x_shift, 0, width/2, height);
bg_right = Bitmap.createBitmap(heat, x_shift, 0, width/2, height);
}
catch (OutOfMemoryError e){
throw new OutOfMemoryError("OutOfMemoryException;DrawWallpaper(); model: " + Build.MODEL + "; LocalizedMessage: "+e.getLocalizedMessage()+"; Message: "+e.getMessage());
}
// Draw backgrounds
c.drawBitmap(bg_left, 0, 0, null);
c.drawBitmap(bg_right, width/2, 0, null);
//...
}
コードの最適化を手伝ってもらえますか?
アップデート
変換マトリックスを使用してビットマップを描画しようとしましたが、遅いです。これが私が試した方法です:
Matrix m = new Matrix();
m.reset();
RectF rect_source = new RectF(x_shift, 0, source_width, original_height);
RectF rect_destination = new RectF(0, 0, width/2, height);
m.setRectToRect(rect_source, rect_destination, Matrix.ScaleToFit.CENTER);
c.drawBitmap(BitmapFactory.decodeResource(res, resource_left), m, null);
本来の画面に収まりません(サイズの計算でエラーが発生したに違いありません)。それは正しい方法ですか?計算を修正すると速くなるでしょうか(下の領域をトリミングします)?