加载全宽高图片

5
<ImageView
    android:id="@+id/bg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop"
    android:src="@drawable/bg" />

@drawable/bg1600 * 1800 (宽 * 高)

我尝试使用

BitmapFactory.decodeResource(getResources(), R.drawable.bg, options);

使用inSampleSize

以下是日志信息:

02-05 05:32:05.841: E/screenWidth in px =(876): 768
02-05 05:32:05.841: E/screenheight in px =(876): 1184
02-05 05:32:05.841: E/screenDensity =(876): 2.0
02-05 05:32:05.841: E/screenDensityDpi =(876): 320
02-05 05:32:05.841: E/decodeSampledBitmapFromResource reqWidth =(876): 768
02-05 05:32:05.851: E/decodeSampledBitmapFromResource reqHeight =(876): 1184
02-05 05:32:05.921: E/decodeSampledBitmapFromResource imageHeight =(876): 1800
02-05 05:32:05.921: E/decodeSampledBitmapFromResource imageWidth =(876): 1600
02-05 05:32:05.921: E/decodeSampledBitmapFromResource imageType =(876): image/jpeg
02-05 05:32:05.951: E/calculateInSampleSize: inSampleSize =(876): 1
02-05 05:32:09.291: E/dalvikvm-heap(876): Out of memory on a 44441616-byte allocation.
02-05 05:32:09.391: E/AndroidRuntime(876): FATAL EXCEPTION: main
02-05 05:32:09.391: E/AndroidRuntime(876): Process: com.example.splash, PID: 876
02-05 05:32:09.391: E/AndroidRuntime(876): java.lang.OutOfMemoryError
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:587)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:422)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:445)
02-05 05:32:09.391: E/AndroidRuntime(876):  at com.example.splash.SecondActivity.decodeSampledBitmapFromResource(SecondActivity.java:103)
02-05 05:32:09.391: E/AndroidRuntime(876):  at com.example.splash.SecondActivity.onCreate(SecondActivity.java:57)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.Activity.performCreate(Activity.java:5231)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.ActivityThread.access$800(ActivityThread.java:135)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.os.Handler.dispatchMessage(Handler.java:102)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.os.Looper.loop(Looper.java:136)
02-05 05:32:09.391: E/AndroidRuntime(876):  at android.app.ActivityThread.main(ActivityThread.java:5017)
02-05 05:32:09.391: E/AndroidRuntime(876):  at java.lang.reflect.Method.invokeNative(Native Method)
02-05 05:32:09.391: E/AndroidRuntime(876):  at java.lang.reflect.Method.invoke(Method.java:515)
02-05 05:32:09.391: E/AndroidRuntime(876):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-05 05:32:09.391: E/AndroidRuntime(876):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-05 05:32:09.391: E/AndroidRuntime(876):  at dalvik.system.NativeStart.main(Native Method)

问题是,对于高度为1184的设备,

inSampleSize将为1(因此没有变化)。
所以,经过所有这些处理是有点无用的,同样会发生OOM错误。

这个单个屏幕显示需要44 MB的内存,我使用以下代码获取:

long totalMem = Runtime.getRuntime().totalMemory();

如果我将图像的src设置为@null,则上述值为3 mb

这是一种可靠的找到应用程序内存使用情况的方法吗?

请帮助我如何加载这样高分辨率的图像而不会出现OOM。


你真的需要使用整张图片吗?难道没有可以从9宫格中组合出来的东西吗?你能展示一下这张图片吗? - gunar
我尝试过了。使用了320 x 350的9-patch并将其设置为背景。问题是,现在它看起来非常暗淡。但是我看到很多应用程序有清晰的全屏图像。 - Archie.bpgc
你的问题是图片太大了,可能需要它的细节层次。有没有一种聪明的方式来组合这张图片?否则,你唯一的选择就是通过失去质量来减小它的尺寸... - gunar
如果您缩小图像的大小,即使针对10英寸设备,它的屏幕尺寸也永远不会与您提到的图像尺寸相同,这将是有益的。 - Rat-a-tat-a-tat Ratatouille
@Rat-a-tat-a-tatRatatouille 这里有很多(链接):http://developer.android.com/guide/practices/screens_support.html#screens-table - Archie.bpgc
5个回答

3
Picasso.with(context).load(R.drawable.bg).into(iv);

使用 Picasso 图片加载器非常高效。请访问链接了解更多信息。

3

0

我遇到了这个问题 - 最终我降低了图像的质量:

    public NSData fixSize(UIImage file)
    {
        if (file.Size.Width > 400 || file.Size.Height > 400)
        {
            // Figure out the ratio
            double ratioX = (double)400 / (double)file.Size.Width;
            double ratioY = (double)400 / (double)file.Size.Height;
            // use whichever multiplier is smaller
            double ratio = ratioX < ratioY ? ratioX : ratioY;

            // now we can get the new height and width
            int newHeight = Convert.ToInt32(file.Size.Height * ratio);
            int newWidth = Convert.ToInt32(file.Size.Width * ratio);
            Console.WriteLine("rescaling image to y:" + newHeight.ToString() + " and x:" + newWidth.ToString());
            file = file.Scale(new Size((int)newWidth, (int)newHeight));
        }

        if (file == null) return null;
        Console.WriteLine("setting image data to quality " + quality.ToString());
        NSData data = file.AsJPEG(quality);
        if (data.Length > 400000)
        {
            quality -= 0.1f;
            if (quality - 0.1f < 0.1f)
            {

            }
            Console.WriteLine("image data still too large will try at " + quality.ToString());
            fixSize(file);
        }
        return data;
    }

正如您所看到的,它循环遍历图像,逐渐降低质量,直到达到可管理的大小。


0

我曾经遇到过相同的问题,但这只是一个简单的错误。

如果你将背景放在drawable文件夹中,这将对你有所帮助。

因为如果你把背景放在drawable文件夹中,它会自动缩放到xhdpi屏幕大小,因此它会尝试加载3200 * 3600像素的图像,这将导致OutOfMemory错误。你需要把图片放在drawable-nodpidrawable-xxhdpi中。我建议选择后者,因为你的图片将被缩小适应低分辨率屏幕(通常也可用内存较少)。


-1

有一些关于编程的教程,包括:

加载大型位图

在哪里可以找到以下内容:

为了避免java.lang.OutOfMemory异常,在解码位图之前,请检查其尺寸,除非您绝对信任源提供的可预测大小的图像数据可以舒适地适应可用内存。

编辑:

我建议使用AQuery (android-query)

//fetch and set the image from internet, cache with file and memory 
aq.id(R.id.image1).image("http://www.vikispot.com/z/images/vikispot/android-w.png");

//returns the cached file by url, returns null if url is not cached
File file = aq.getCachedFile(url);

是的,在解码之前检查位图的尺寸。正如我在问题中解释的那样,尺寸导致inSampleSize = 1。这意味着我必须使用整个图像。 - Archie.bpgc
我从链接开始。我上面的代码来自于那个链接。 - Archie.bpgc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接