【问题标题】:Loading an image in android allocates a large memory在android中加载图像会分配很大的内存
【发布时间】:2012-11-09 10:34:42
【问题描述】:

我使用尺寸为 720X1136 的图像作为我的应用程序的启动屏幕,该应用程序仅针对三星 Galaxy Nexus 手机。实际文件大小为 513Kb(从浏览器中找到)。当活动调用 onCreate 方法并设置内容视图时,日志中提到了 13.5 MB 的内存分配。

这是我在后台加载图片的活动。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:orientation="vertical">

        <ImageView android:src="@drawable/splashscreen"
                android:id="@+id/splashscreen"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               />

        <WebView xmlns:android="http://schemas.android.com/apk/res/android"
                    android:visibility="invisible"
                 android:id="@+id/webview"
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent"
        />

</RelativeLayout>

如何减少这种内存分配?

谢谢

【问题讨论】:

  • 在 relativelayout 中将其用作背景可能会节省一些内存...
  • 您可以在使用后尝试完成闪屏活动。
  • 您需要将 Image by Code 设置为您的根布局,就像我在 android 中给出的那样。
  • 我尝试了由代码设置的 1 Mb 图像和直接在布局中设置的图像,并为由布局设置的第一个图像从应用程序输入和输出内存崩溃。

标签: java android memory-management android-memory


【解决方案1】:

使用@drawable/splashscreen 这个图像作为 9-Patch 图像 那么它会减少内存分配

【讨论】:

    【解决方案2】:

    这是解决问题的步骤。

    mRelativeLayout=(RelativeLayout)findViewById(R.id.relative_view);
            intializeScreenSize();
    
            mBitmap=decodeSampledBitmapFromResource(getResources(),R.drawable.splash_background,width,height);
            mDrawable=new BitmapDrawable(getResources(), mBitmap);
            mRelativeLayout.setBackgroundDrawable(mDrawable);
    
    
    
    
    public static Bitmap decodeSampledBitmapFromResource(Resources res,
                int resId, int reqWidth, int reqHeight) {
    
            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(res, resId, options);
    
            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth,
                    reqHeight);
    
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeResource(res, resId, options);
        }
    
    
    
        public void intializeScreenSize(){
    
            DisplayMetrics displaymetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
            height= displaymetrics.heightPixels;
            width= displaymetrics.widthPixels;
        }
    
    
        public static int calculateInSampleSize(BitmapFactory.Options options,
                int reqWidth, int reqHeight) {
            // Raw height and width of image
            final int height = options.outHeight;
            final int width = options.outWidth;
            int inSampleSize = 1;
    
            if (height > reqHeight || width > reqWidth) {
                if (width > height) {
                    inSampleSize = Math.round((float) height / (float) reqHeight);
                } else {
                    inSampleSize = Math.round((float) width / (float) reqWidth);
                }
            }
            return inSampleSize;
        }
    

    这里有一些与在 android 中加载位图相关的链接。 SO Answer Load Bitmap Efficiently

    【讨论】:

      【解决方案3】:

      13mb 很好,并且在限制范围内。每当此初始屏幕消失时,位图将被回收,内存将重新用于您的应用程序的其余部分。

      您可以用来尝试最小化这种内存占用的技巧是:

      。使用 9 补丁来拉伸图像的边框(如果设计允许)

      。降低图像质量(看起来很糟糕)

      【讨论】:

        【解决方案4】:

        正如Alex Orlov 所说:“磁盘上的大小与内存中位图的大小无关。在第一种情况下,图像被压缩,另一方面,位图只是一组原始像素。 "然而,即使考虑到它被存储为原始图像,20MB 仍然太多了。如果我们考虑每个像素 4B,那将是 5Mpix 图片,但您发布的图片肯定更小。

        我遇到了类似的问题:我正在加载一个具有 8MB 原始格式的图像,但是为它分配了 32MB。后来我发现这是由 dpi 缩放引起的。如果您的图像在“drawable”文件夹中,它将根据当前屏幕 dpi 自动缩放。我有一个 XHDPI 屏幕,所以我的图像水平缩放 2 倍,垂直缩放 2 倍,这就是它占用 4 倍更多内存的原因。

        您可以在此处找到有关 dpi 工作原理的更多信息:http://developer.android.com/guide/practices/screens_support.html

        如果您不想使用这个自动 android 功能并自己缩放图像,只需将“drawable”文件夹重命名为“drawable-nodpi”即可。 “drawable”文件夹中标记为“nodpi”的所有图像都将按原样加载。

        【讨论】:

          【解决方案5】:

          没有人需要像素完美的闪屏,您可以轻松地将图像尺寸缩小到原来的一半,这将为您节省 3/4 的内存占用。

          另一方面,我建议完全避免启动画面,这里有一篇关于这个主题的好文章:"Splash screens are evil, don’t use them!",否则你可能会在谷歌搜索“启动画面是邪恶的”并获得更多反对使用它们的论据。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-07-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-10-11
            • 1970-01-01
            相关资源
            最近更新 更多