我觉得很难处理OutOfMemoryExceptions很难在Android中管理。 现在,我总是首先在PhotoShop中调整图像大小,然后检查不同的设备和模拟器,看看我能在多大程度上突破极限。
我当前应用程序的目标是在其上输入输入图像,地图文本和图像并将其保存为PDF。 现在我正在使用大约620x842和250kb的图像,输出不够好。 原版是2480x3368和482kb。
毫无疑问,使用原始文件会导致OutOfMemoryExceptions。 但我想知道如何关闭我可以得到原来的。
有关此的任何想法或提示吗?
答案 0 :(得分:3)
原作是2480x3368和482kb
您的图像大小和文件大小令人困惑。 482KB是文件的大小,是压缩图像。
2480x3368在32位ARGB中实际上是33MB。 (这对于内存中的单个对象来说很重要,可以立即分配)
文件的大小与图像占用的内存大小无关。
Nota:这有点偏离主题,可能应该是评论,但对评论格式来说太长了。
答案 1 :(得分:1)
您是否正在根据google guide解码文件?这为我解决了outOfMemoryException的问题。现在我可以轻松解码像 星系SII上的2676x3326
答案 2 :(得分:0)
您可以在调用BitmapFactory.decodeFile(String,Options)时使用Bitmap.Options
通过设置inSampleSize = 2,您可以获得尺寸除以2的结果位图。
答案 3 :(得分:0)
你可以试试这个:
<activity
android:name="..."
android:configChanges="orientation|keyboardHidden"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:largeHeap="true" >
</activity>
有时候它会起作用,有时它会起作用。请记住,此大小是特定于设备的,因此如果您希望应用程序公开,则应调整所有所需大小的图像大小。我见过的最低价是三星银河的名气。它的heep不会加载大于2048x2048的图像。
如果您想加载大量图片并且内存不足,可以尝试使用thirparty lib,如:http://square.github.io/picasso/。它对我来说非常好,并处理android nativly所有的位图问题。
真正的问题是图片的大小。即使图片具有300kb或400kb的尺寸,当你将其放大以适应屏幕尺寸时,它也会变成非常大的位图,如20或30 mb,这将溢出该线程的堆。
答案 4 :(得分:0)
您可以使用BitmapFactory获取图像的边界,然后加载适合当前内存的较小版本的图像:
/**
* Decodes the given inputstream into a Bitmap, scales the bitmap to the
* required height and width if image dimensions are bigger. Note: the
* decoder will try to fulfill this request, but the resulting bitmap may
* have different dimensions that precisely what has been requested.
*
* @param _inputStreamJustDecode The input stream for bound decoding
* @param _inputStreamData The input stream for image decoding
* @param _preview true to generate a preview image, false to generate a high quality image
* @return
*/
private Bitmap decodeSampledBitmapFromResource(InputStream _inputStreamJustDecode,InputStream _inputStreamData) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(_inputStreamJustDecode, null, options);
float imageSize = options.outWidth * options.outHeight * 4;
float scaleFactor = 1;
long availableMem = getAvailableMemory(mContext);
//new image should not use more than 66% of the available memory
availableMem*=0.66f;
if(imageSize > availableMem){
scaleFactor = (float)availableMem / imageSize;
}
float maxDimen = options.outWidth > options.outHeight ? options.outWidth : options.outHeight;
//Don't let the image get to big.
if(maxDimen * scaleFactor > Constant.MAX_TEXTURE_SIZE ){
scaleFactor = Constant.MAX_TEXTURE_SIZE/maxDimen;
}
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, options.outWidth*scaleFactor,
options.outHeight*scaleFactor);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
// set other options
options.inPurgeable = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeStream(_inputStreamData,null,options);
}
/**
* Returns the currently available memory (ram) in bytes.
* @param _context The context.
* @return The available memory in bytes.
*/
public long getAvailableMemory(Context _context){
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
ActivityManager activityManager = (ActivityManager) _context.getSystemService(Activity.ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem;
return availableMegs;
}
注意:两个输入流都来自同一个资源,但由于在解码边界后无法回放流,因此需要一个新流。