我使用RecyclerView和CardView进行布局,并希望在屏幕上显示横跨4张卡片的水印。我将水印图像切割成4张单独的图像,每张图片一张(每张图片已经有我想要显示的尺寸)。为了显示图像,我在每个卡的.xml文件中使用ImageView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardview"
android:layout_width="415dp"
android:layout_height="89dp"
android:layout_marginTop="0dp"
android:elevation="100dp"
card_view:cardBackgroundColor="#ffffff">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/watermark_card1"
android:scaleType="centerCrop" />
.
.
.
</RelativeLayout>
</android.support.v7.widget.CardView>
这个工作正常,而我只加载4个图像中的2个,但是当我加载第3个图像时,我收到以下错误:
java.lang.OutOfMemoryError:无法分配带有4194304个空闲字节的210446976字节分配和101MB直到OOM
我认为这是因为图像都非常大(521K,976K,611K和933K),我想知道如何使用更少的内存并避免出现OutOfMemory错误。任何建议都将不胜感激,谢谢!
答案 0 :(得分:1)
您必须调整图像质量或降低图像质量。并使用像volly或picasso这样的图像库。这个库可以解决与图像有关的各种问题。
答案 1 :(得分:1)
在AndroidManifest.xml文件中,在应用程序标记内添加以下行
android:largeHeap="true"
但是,请记住这只会增加堆内存并为您提供解决方案。但是,这不是最好的做法。你应该正确回收你的记忆。
参考链接
Strange out of memory issue while loading an image to a Bitmap object
答案 2 :(得分:0)
您可以在使用BitmapFactory创建图像时对图像进行缩减采样。您只需将图像包含为资源并获取输入流,然后创建缩减采样的Bitmap对象。这样,您可以根据设备,屏幕大小,可用内存等来决定图像的大小。创建Bitmap对象后,使用ImageView.setImageBitmap()将其设置到图像视图中。以下是下采样方法的示例 -
public static Bitmap decodeBitmap(InputStream decodeStream, byte[] decodeArray) throws IOException
{
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = null;
boolean useStream = ((decodeStream != null) ? true : false);
int actualFileSize;
// get the decoded object size without actually decoding and creating the object
options.inJustDecodeBounds = true;
if (useStream)
BitmapFactory.decodeStream(decodeStream, null, options);
else
BitmapFactory.decodeByteArray(decodeArray, 0, decodeArray.length, options);
actualFileSize = options.outWidth * options.outHeight * 4;
if (useStream)
decodeStream.reset(); // reset the data - we assume the underlying input stream implements reset() in a
// way that will not throw an exception in the case where the stream is not marked
if (actualFileSize > MAX_BYTES)
{
options = new BitmapFactory.Options(); // recreate the options to get the defaults back
if (actualFileSize/4 <= MAX_BYTES)
options.inSampleSize = 2; // a sample size of 2 has 1/4th the pixels
else if(actualFileSize/16 <= MAX_BYTES)
options.inSampleSize = 4; // a sample size of 4 has 1/16th the pixels
else
options.inSampleSize = 8; // if it is still too big, attempt a sample size of 8 (1/64th the pixels)
if (useStream)
bitmap = BitmapFactory.decodeStream(decodeStream, null, options);
else
bitmap = BitmapFactory.decodeByteArray(decodeArray, 0, decodeArray.length, options);
}
else
{
if (useStream)
bitmap = BitmapFactory.decodeStream(decodeStream);
else
bitmap = BitmapFactory.decodeByteArray(decodeArray, 0, decodeArray.length, null);
}
return bitmap;
}
最后,当您在代码中加载图像时,我发现在每次调用decodeStream()之前和之后强制进行垃圾收集(通过System.gc())会很有帮助。完成Bitmap对象后,使用Bitmap.recycle()显式处理它们的内存。在Android上使用大位图进行内存管理可能会有点毛茸茸 - 这里有一些其他的建议 - https://developer.android.com/training/displaying-bitmaps/manage-memory.html
希望这有帮助。
答案 3 :(得分:0)
OutOfMemory错误意味着您的图片尺寸很大,因此要么降低图像质量要么使用图像库以便缓存图像,如果它仍然没有帮助,那么在清单中的应用程序标记中使bigheap = true文件。
答案 4 :(得分:0)
要避免此错误,您必须遵循此链接中的建议: https://developer.android.com/training/displaying-bitmaps/load-bitmap.html (并查看接下来的两个教程)。
但最简单的方法是使用一个受欢迎的图书馆(如其中一个答案所述) - 例如毕加索(http://square.github.io/picasso/)。