为什么不同的Android设备使用不同的内存量来加载图像?

时间:2015-10-29 22:24:10

标签: java android image memory-management android-image

我正和朋友一起制作游戏,我们需要加载大量图片,所以我一直试图通过了解他们占用多少内存来弄清楚如何确定图像的分辨率。我已经在几个Android设备上运行测试,以便在崩溃之前尽可能多地将图像加载到内存中,并且似乎不同的设备可以加载任意数量的图像。这真的让我失望,因为似乎没有任何理由。

据我所知,图像在内存中应占用的内存量是宽度x高度x颜色所需的字节数。在我的测试中,我使用了100x100x2,因为我对非透明图像使用了16位着色。这意味着每张图像应占用大约20000字节的内存,或大约20KB。我也启用了大堆,但是使用正常堆扩展的测试方式相同。测试结果非常一致,我在每台设备上运行了几次,结果通常完全相同。

在我的手机上,大堆有256MB,我可以加载4973这些图片,大约应该是99.46MB。在具有完全相同的大堆大小的朋友平板电脑上,他可以加载11164这些图像,相当于223.28MB。

在我的平板电脑上,它有一个512MB的大堆,它加载了6117个图像,这是122.34MB,而在我的朋友手机上,它只能加载1479个图像,其中任何一个都是最少的,它应该只有29.58MB。为什么堆大小为256MB的设备能够加载11164个图像,而堆大小为512MB的设备只能加载1479个图像?

所有测试都使用完全相同的图像和16位颜色格式,但结果都没有任何意义。分辨率是否起作用?如果是这样,我的朋友手机和我的平板电脑有非常相似的分辨率,这是没有任何意义的...似乎图像由于某种原因在不同的设备上占用不同的空间。在内存监视器中,具有512MB大堆的两个设备在崩溃之前都使用了所有内存。这意味着完全相同的程序在两个不同的设备上占用不同的内存量,而它所做的就是加载图像。如何确定可在任何设备上使用的图像数量,或在哪些设备上使用的分辨率?也许我把测试写错了,或者我误解了什么?

这是我测试的代码:

package foreal.testimagelimit;    

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Bitmap [] bitmaps = new Bitmap[8675309];

        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(new GameView(this));
        View decorView = getWindow().getDecorView();
        getWindow().getDecorView().setBackgroundColor(Color.BLACK);
        int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);

        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        int largeAmount = manager.getLargeMemoryClass();
        int normalAmount = manager.getMemoryClass();
        Log.d("foreal.testimagelimit", "Normal Memory: " + normalAmount);
        Log.d("foreal.testimagelimit","Large Memory: "+largeAmount);

        Resources r = this.getResources();
        for(int i=0; i<bitmaps.length; i++) {
            bitmaps[i] = loadBitmap(r.getDrawable(R.drawable.test100x100));
            Log.d("foreal.testimagelimit",(i+1)+" images loaded");
        }            
    }

    class GameView extends View {
        public GameView(Context context) {
            super(context);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            invalidate();
        }
    }

    public static Bitmap loadBitmap(Drawable sprite, Bitmap.Config bitmapConfig) {
        int width = sprite.getIntrinsicWidth();
        int height = sprite.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, bitmapConfig);
        Canvas canvas = new Canvas(bitmap);
        sprite.setBounds(0, 0, width, height);
        sprite.draw(canvas);
        return bitmap;
    }

    public static Bitmap loadBitmap(Drawable sprite) {
        return loadBitmap(sprite, Bitmap.Config.RGB_565);
    }
}

0 个答案:

没有答案