Android 简单静态库中出现内存不足异常
我使用的是一个简单的静态图像库,其中我加载了至少28个图像,每个图像的大小都在150kb以下 我注意到两个问题: 1) 慢卷轴 2) 当我执行此活动两次或三次时出现内存不足异常 有谁能告诉我这里的问题是什么以及如何解决 任何帮助都将不胜感激 日志目录:Android 简单静态库中出现内存不足异常,android,gridview,imageview,android-gallery,Android,Gridview,Imageview,Android Gallery,我使用的是一个简单的静态图像库,其中我加载了至少28个图像,每个图像的大小都在150kb以下 我注意到两个问题: 1) 慢卷轴 2) 当我执行此活动两次或三次时出现内存不足异常 有谁能告诉我这里的问题是什么以及如何解决 任何帮助都将不胜感激 日志目录: 03-15 15:32:55.899: E/AndroidRuntime(14662): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 03-15 15:32:55.899:
03-15 15:32:55.899: E/AndroidRuntime(14662): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.content.res.Resources.loadDrawable(Resources.java:1709)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.content.res.Resources.getDrawable(Resources.java:581)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.ImageView.resolveUri(ImageView.java:501)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.ImageView.setImageResource(ImageView.java:280)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.tackfu.Art$ImageAdapter.getView(Art.java:84)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.obtainView(AbsListView.java:1515)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.makeAndAddView(GridView.java:1269)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.makeRow(GridView.java:315)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.fillDown(GridView.java:268)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.fillGap(GridView.java:235)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4063)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.onTouchEvent(AbsListView.java:2471)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.View.dispatchTouchEvent(View.java:3885)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1750)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1135)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1734)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2216)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewRoot.handleMessage(ViewRoot.java:1887)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.os.Handler.dispatchMessage(Handler.java:99)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.os.Looper.loop(Looper.java:130)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.app.ActivityThread.main(ActivityThread.java:3687)
03-15 15:32:55.899: E/AndroidRuntime(14662): at java.lang.reflect.Method.invokeNative(Native Method)
03-15 15:32:55.899: E/AndroidRuntime(14662): at java.lang.reflect.Method.invoke(Method.java:507)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
03-15 15:32:55.899: E/AndroidRuntime(14662): at dalvik.system.NativeStart.main(Native Method)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.art);
GridView gridview = (GridView) findViewById(R.id.gridv
gridview.setAdapter(new ImageAdapter(this));
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.i1, R.drawable.i2,
R.drawable.i3, R.drawable.i4,
R.drawable.i5, R.drawable.i6,
R.drawable.i7, R.drawable.i8,
R.drawable.i9, R.drawable.i10,
R.drawable.i11, R.drawable.i12,
R.drawable.i13,R.drawable.i14,
R.drawable.i15,R.drawable.i16,
R.drawable.i17,R.drawable.i18,
R.drawable.i19,R.drawable.i20,
R.drawable.i21, R.drawable.i22,
R.drawable.i23, R.drawable.i24,
R.drawable.i26, R.drawable.i28,
R.drawable.i29, R.drawable.i30
};
}
活动代码:
03-15 15:32:55.899: E/AndroidRuntime(14662): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.content.res.Resources.loadDrawable(Resources.java:1709)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.content.res.Resources.getDrawable(Resources.java:581)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.ImageView.resolveUri(ImageView.java:501)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.ImageView.setImageResource(ImageView.java:280)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.tackfu.Art$ImageAdapter.getView(Art.java:84)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.obtainView(AbsListView.java:1515)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.makeAndAddView(GridView.java:1269)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.makeRow(GridView.java:315)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.fillDown(GridView.java:268)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.GridView.fillGap(GridView.java:235)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4063)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.widget.AbsListView.onTouchEvent(AbsListView.java:2471)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.View.dispatchTouchEvent(View.java:3885)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1750)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1135)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1734)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2216)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.view.ViewRoot.handleMessage(ViewRoot.java:1887)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.os.Handler.dispatchMessage(Handler.java:99)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.os.Looper.loop(Looper.java:130)
03-15 15:32:55.899: E/AndroidRuntime(14662): at android.app.ActivityThread.main(ActivityThread.java:3687)
03-15 15:32:55.899: E/AndroidRuntime(14662): at java.lang.reflect.Method.invokeNative(Native Method)
03-15 15:32:55.899: E/AndroidRuntime(14662): at java.lang.reflect.Method.invoke(Method.java:507)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
03-15 15:32:55.899: E/AndroidRuntime(14662): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
03-15 15:32:55.899: E/AndroidRuntime(14662): at dalvik.system.NativeStart.main(Native Method)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.art);
GridView gridview = (GridView) findViewById(R.id.gridv
gridview.setAdapter(new ImageAdapter(this));
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.i1, R.drawable.i2,
R.drawable.i3, R.drawable.i4,
R.drawable.i5, R.drawable.i6,
R.drawable.i7, R.drawable.i8,
R.drawable.i9, R.drawable.i10,
R.drawable.i11, R.drawable.i12,
R.drawable.i13,R.drawable.i14,
R.drawable.i15,R.drawable.i16,
R.drawable.i17,R.drawable.i18,
R.drawable.i19,R.drawable.i20,
R.drawable.i21, R.drawable.i22,
R.drawable.i23, R.drawable.i24,
R.drawable.i26, R.drawable.i28,
R.drawable.i29, R.drawable.i30
};
}
大小为150KB的28个图像的内存约为4MB。加上应用程序数据,它不能放入小堆中。您可以设置:
但这种方法看起来是一种变通方法,因为你有无限的内存,而且图像数量的增加可能再次导致这种错误。您还应该使用延迟加载或按设备屏幕大小调整图像大小。在不使用位图时回收位图。使用视图支架以获得更好的性能。 . 我建议你看看这个链接。适用于listview的内容也适用于gridview,视频中也谈到了它。视频中还有一个关于视图支架的对话,这正是您应该使用的,以避免内存泄漏 此外,还讨论了如何避免内存泄漏 。请参阅章节将缩小的版本加载到内存中 使用MAT分析仪检查内存泄漏
考虑一些提示。慢滚动的原因很简单。每次创建视图时,您都在UI线程中加载图像。您应该将加载委托给另一个优先级较低的线程。若您愿意,可以在UI线程中加载缩略图以快速显示某些内容,然后在后台加载完全分辨率 请记住,Android有很多巧妙的技巧可以让你的应用程序变得漂亮,但你必须明智地使用它们。例如,Android将静态视图缓存在所谓的图形缓存中,但对于ImgaeViews来说,这是毫无意义的,因为它需要额外的内存,而不提供任何内容。使用硬件加速的UI会使用更多的内存,因为每个视图缓存都使用两个texuture的幂。这意味着100x35px按钮将占用128x64x4字节的额外内存。Android还将尝试使用某种类型的抗锯齿,比如线性纹理采样器-它很好,但需要大量CPU时间,您可能需要关闭它 通过setImageResource加载图像几乎没有控制权。您可能希望自己加载图像,以便更精确地控制加载和卸载。您还可以稍微缓存图像。LRU缓存是为此类用途创建的类的一个很好的示例:。您可以加载当前图像并预加载左侧和右侧的图像。当用户返回到上一个图像时,您将把它保存在内存中
此外,如果希望使用暴力,可以使用NativeBuffer:缓存图像。这将迫使你重新设计你的图库,但它会大大加快图像密集型应用程序的速度。你是否阅读了这篇关于内存不足的帖子,如果你启动活动,然后完成它,然后重新启动它,然后离开内存,我想你有一个漏洞,如果你指出这个漏洞,我将不胜感激。我可以给你一个建议,粗暴地取消对activity.finish中的所有内容的引用,比如myvar=null并调用System.gc()。在视频中,这些家伙给出了一个关于android的警告:largeHeap=“true”仅仅因为需要大堆就没有用。堆越大,Garbadge收集发生的频率就越高。您是对的,大堆不是解决方案。谢谢你的链接。最好的答案!我有一个类似的问题(试图为十几个图像分配~5MB),几个小时都无法解决。这个参数就是我需要的。谢谢raghunandan,你有详细的答案,它帮助我解决了这个问题。很高兴它有帮助。您将显示28幅图像。有些应用程序有更多功能。因此,显示28幅图像不会给您带来内存不足错误。如果您有效地加载它们,就不应该耗尽内存。