Android java.lang.OutOfMemoryError - BitmapFactory.decode(strPath)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20441644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.OutOfMemoryError - BitmapFactory.decode(strPath)
提问by Sun
I am getting java.lang.OutOfMemoryError, whenever i am calling UploadActivity.java
每当我调用UploadActivity.java时,我都会收到java.lang.OutOfMemoryError
Line Number 176 is:
第 176 行是:
Bitmap bm = BitmapFactory.decodeFile(strPath);
View my Log:
查看我的日志:
12-07 17:57:10.585: E/AndroidRuntime(16708): FATAL EXCEPTION: main
12-07 17:57:10.585: E/AndroidRuntime(16708): java.lang.OutOfMemoryError
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:650)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:389)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:449)
12-07 17:57:10.585: E/AndroidRuntime(16708): at com.example.camera.UploadActivity$ImageAdapter.getView(UploadActivity.java:176)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.AbsListView.obtainView(AbsListView.java:2465)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.ListView.makeAndAddView(ListView.java:1775)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.ListView.fillDown(ListView.java:678)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.ListView.fillFromTop(ListView.java:739)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.ListView.layoutChildren(ListView.java:1628)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.AbsListView.onLayout(AbsListView.java:2300)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.View.layout(View.java:14063)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewGroup.layout(ViewGroup.java:4607)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:948)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.View.layout(View.java:14063)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewGroup.layout(ViewGroup.java:4607)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.View.layout(View.java:14063)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewGroup.layout(ViewGroup.java:4607)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1655)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1513)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.LinearLayout.onLayout(LinearLayout.java:1426)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.View.layout(View.java:14063)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewGroup.layout(ViewGroup.java:4607)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.View.layout(View.java:14063)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewGroup.layout(ViewGroup.java:4607)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1996)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1817)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1114)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4520)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.Choreographer.doCallbacks(Choreographer.java:555)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.Choreographer.doFrame(Choreographer.java:525)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.os.Handler.handleCallback(Handler.java:615)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.os.Handler.dispatchMessage(Handler.java:92)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.os.Looper.loop(Looper.java:137)
12-07 17:57:10.585: E/AndroidRuntime(16708): at android.app.ActivityThread.main(ActivityThread.java:4921)
12-07 17:57:10.585: E/AndroidRuntime(16708): at java.lang.reflect.Method.invokeNative(Native Method)
12-07 17:57:10.585: E/AndroidRuntime(16708): at java.lang.reflect.Method.invoke(Method.java:511)
12-07 17:57:10.585: E/AndroidRuntime(16708): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
12-07 17:57:10.585: E/AndroidRuntime(16708): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
12-07 17:57:10.585: E/AndroidRuntime(16708): at dalvik.system.NativeStart.main(Native Method)
UploadActivity.java:-
上传Activity.java:-
public class ImageAdapter extends BaseAdapter
{
private Context context;
public ImageAdapter(Context c)
{
// TODO Auto-generated method stub
context = c;
}
public int getCount() {
// TODO Auto-generated method stub
return ImageList.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_upload, null);
}
// ColImgName
TextView txtName = (TextView) convertView.findViewById(R.id.ColImgName);
strPath = ImageList.get(position).toString();
// Get File Name
fileName = strPath.substring( strPath.lastIndexOf('/')+1, strPath.length() );
File file = new File(strPath);
@SuppressWarnings("unused")
long length = file.length();
txtName.setText(fileName);
// Image Resource
ImageView imageView = (ImageView) convertView.findViewById(R.id.ColImgPath);
Bitmap bm = BitmapFactory.decodeFile(strPath);
imageView.setImageBitmap(bm);
// ColStatus
final ImageView txtStatus = (ImageView) convertView.findViewById(R.id.ColStatus);
txtStatus.setImageResource(R.drawable.bullet_button);
// progressBar
final ProgressBar progress = (ProgressBar) convertView.findViewById(R.id.progressBar);
progress.setVisibility(View.GONE);
//btnUpload
final ImageButton btnUpload = (ImageButton) convertView.findViewById(R.id.btnUpload);
btnUpload.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Upload
btnUpload.setEnabled(false);
startUpload(position);
}
});
return convertView;
}
}
回答by Shakeeb Ayaz
You need to recycle Bitmap object .
您需要回收位图对象。
Bitmap bm = BitmapFactory.decodeFile(strPath);
imageView.setImageBitmap(bm);
After above lines of code in your get view just add the code written below ///now recycle your bitmap this will free up your memory on every iteration
在获取视图中的上述代码行之后,只需添加下面编写的代码 ///现在回收您的位图,这将在每次迭代时释放您的内存
if(bm!=null)
{
bm.recycle();
bm=null;
}
After this also if you are getting same error the
在此之后,如果您遇到同样的错误
Replace below code
替换下面的代码
Bitmap bm = BitmapFactory.decodeFile(strPath);
imageView.setImageBitmap(bm);
with
和
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bm = BitmapFactory.decodeFile(strPath,options);
imageView.setImageBitmap(bm);
Use inSampleSize to load scales bitmaps to memory. Using powers of 2 for inSampleSize values is faster and more efficient for the decoder. However, if you plan to cache the resized versions in memory or on disk, it's usually still worth decoding to the most appropriate image dimensions to save space.
使用 inSampleSize 将比例位图加载到内存中。对 inSampleSize 值使用 2 的幂对解码器来说更快、更有效。但是,如果您计划将调整大小的版本缓存在内存或磁盘上,通常仍然值得解码为最合适的图像尺寸以节省空间。
For more see Loading Large Bitmaps Efficiently
回答by Milan Pansuriya
Use this in manifest file in Application tag
在应用程序标签的清单文件中使用它
android:largeHeap="true"
回答by Santhosh
before calling Bitmap bm=BitmapFactory.decodeFile(strPath);
call this.. Bitmap bm =decodeSampledBitmapFromResource(strPath,reqWidth,reqHeight);
if you get again java.lang.OutOfMemoryError then let me know
在调用 Bitmap 之前 bm=BitmapFactory.decodeFile(strPath);
调用这个.. Bitmap bm =decodeSampledBitmapFromResource(strPath,reqWidth,reqHeight);
如果你再次遇到 java.lang.OutOfMemoryError 然后让我知道
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;
}
public static Bitmap decodeSampledBitmapFromResource(String strPath,int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(strPath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options,reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(strPath, options);;
}
回答by saiful103a
It's an optimisation problem for your application. You are getting OutOfMemoryError because when you are doing BitmapFactory.decodeFile(strPath) android is trying to allocate memory for that bitmap. In your case system can't find enough free space to allocate and that's why you are getting this error.
这是您的应用程序的优化问题。您收到 OutOfMemoryError 是因为当您执行 BitmapFactory.decodeFile(strPath) 时,android 正在尝试为该位图分配内存。在您的情况下,系统找不到足够的可用空间来分配,这就是您收到此错误的原因。
Now as i can see from your code you are trying to show list of images using ImageAdapter. In that case your imageview must have smaller width and height than actual image.
现在,正如我从您的代码中看到的,您正在尝试使用 ImageAdapter 显示图像列表。在这种情况下,您的图像视图的宽度和高度必须小于实际图像。
To give you a more generalised idea here's what is happening:
为了让您有一个更普遍的想法,这是正在发生的事情:
- ImageView width * height = 100dp * 100dp
- Image width * height = 800px * 800px.
- ImageView 宽 * 高 = 100dp * 100dp
- 图片宽度 * 高度 = 800px * 800px。
In this scenario though our imageview width-height is 100 * 100 but we are trying to set 800*800 image as it's background. And this definitely is not an efficient way because the system will allocate memory for 800*800px image whereas 100*100 would do.
在这种情况下,虽然我们的图像视图宽高是 100 * 100,但我们试图将 800 * 800 图像设置为背景。这绝对不是一种有效的方式,因为系统会为 800*800px 的图像分配内存,而 100*100 可以。
That's why before you do any decoding of bitmap you should sample the bitmap so that only 100*100 worth of memory is allocated.
这就是为什么在对位图进行任何解码之前,您应该对位图进行采样,以便仅分配 100*100 的内存。
You will find a more detail version of this explanation here
您将在此处找到此解释的更详细版本
回答by Rudra
I had the same problem. I incorporated all the above suggestions, but I still had the problem of java.lang.outOfMemoryError. After a lot of tweaking around, what finally worked was scaling down image dimensions (and size). Originally, I had images of dimensions 800 x 1000 sorts. I rescaled them to about 60 x 80 (because that's what I needed), and it worked!
我有同样的问题。我综合了以上所有建议,但我仍然遇到了 java.lang.outOfMemoryError 的问题。经过大量调整后,最终起作用的是缩小图像尺寸(和大小)。最初,我有尺寸为 800 x 1000 的图像。我将它们重新缩放到大约 60 x 80(因为这是我需要的),并且它起作用了!
So besides following all advice you get on stackoverflow and other sites about this issue, also do a grassroots check of your image sizes and dimensions. Will save you a lot of headache.
因此,除了遵循您在 stackoverflow 和其他网站上获得的有关此问题的所有建议之外,还要对图像大小和尺寸进行基层检查。将为您省去很多麻烦。