在我的应用程序中我创建了一些按钮点击按钮点击我拍摄的屏幕视图,并且我将这个图像与2个徽标合并,带有5,10图像的应用程序没有问题但是有更多10个图像我得到了一个内存不足,这是代码:
@Override
public void onScreenshotImage(ImageStruct image) {
//do whatever you want with the image parameter
super.onScreenshotImage(image);
Bitmap a = image.getBitmap();
ResizeImage resize = new ResizeImage(a);
resize.execute();
Log.d("onScreenshot","get image");
}
private class ResizeImage extends AsyncTask<String, Void, String> {
Bitmap bottomImage;
public ResizeImage (Bitmap image) {
bottomImage = image;
}
@Override
protected String doInBackground(String... params) {
Bitmap output = Bitmap.createBitmap(bottomImage.getWidth(), bottomImage.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(bottomImage, 0, 0, paint);
Bitmap a = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
canvas.drawBitmap(a, 0, 0, paint);
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.logo_1);
canvas.drawBitmap(b, bottomImage.getWidth()-(b.getWidth()+20), bottomImage.getHeight()-(b.getHeight()+30), paint);
String outputString = Environment.getExternalStorageDirectory().getPath() + "/images/";
File folder_thumb= new File(outputString);
if (!folder_thumb.exists()) {
folder_thumb.mkdirs();
}
String tmpImg = String.valueOf(System.currentTimeMillis()) + ".png";
OutputStream os = null;
try {
os = new FileOutputStream(outputString + tmpImg);
output.compress(Bitmap.CompressFormat.PNG, 100, os);
os.close();
}
catch(IOException e) {
Log.e("combineImages", "problem saving images", e);
}
a.recycle();
b.recycle();
output.recycle();
bottomImage.recycle();
return "Executed";
}
@Override
protected void onPostExecute(String result) {
System.gc();
Runtime.getRuntime().gc();
}
}
PS。第一个功能是在metaio中获取图像的功能。 错误在哪里?
编辑:我看到等待任务结束时内存不超过mb,而删除块(一个简单的布尔值)内存也会达到100mb。
答案 0 :(得分:0)
你可以做两件事:
如果您选择选项2 ,请使用Picasso。查看他们网站上的示例。在Android上加载图片并没有更简单的API,而且它是更好的选择。
示例API调用如下所示:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
如果您选择选项1 ,您将有更多工作,您可以按照以下提示操作:
在官方Android开发者网站上有一篇关于Loading Large Bitmaps Efficiently的文章,值得一读。它解释了问题并提出了可能的解决方案。
我们可以分三步处理内存问题:
您可以使用以下代码段:
public static Bitmap decodeSampledBitmap(String filePath, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath,options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath,options);
}
您还需要从Android documentation借用calculateInSampleSize
方法:
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) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
答案 1 :(得分:-1)
在AndroidManifest.xml
<application />
标记
android:largeHeap="true"
请记住关于此的文档警告(https://developer.android.com/training/articles/memory.html):
在非常特殊的情况下,您可以通过将largeHeap属性设置为&#34; true&#34;来请求更大的堆大小。在清单标签中。如果这样做,可以调用getLargeMemoryClass()来估算大堆大小。
但是,请求大堆的功能仅适用于一小部分可以证明需要消耗更多RAM的应用程序(例如大型照片编辑应用程序)。 永远不要仅仅因为你的内存耗尽而你需要快速修复而需要大堆 - 你只有在你确切知道所有内存的分配位置以及为什么必须分配时才使用它保留。然而,即使您确信您的应用程序可以证明大堆的合理性,您也应该尽可能避免请求它。使用额外的内存将越来越不利于整体用户体验,因为在任务切换或执行其他常见操作时,垃圾收集将花费更长时间并且系统性能可能会更慢。
此外,所有设备上的大堆大小都不相同,并且在RAM有限的设备上运行时,大堆大小可能与常规堆大小完全相同。因此,即使您确实请求大堆大小,也应该调用getMemoryClass()来检查常规堆大小,并努力始终保持低于该限制。