简单静态库的情况下内存不足

时间:2013-03-15 10:34:54

标签: android gridview imageview android-gallery

我正在使用一个简单的静态图片库,其中我正在加载至少28张不同大小,低于150kb的28张图片。

我发现了两个问题:

1)慢滚动 2)当我两次三次参加这项活动时出现内存异常。

任何人都会指导我这里有什么问题以及如何解决它?

任何帮助将不胜感激

Log Cat:

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
            };
        }

3 个答案:

答案 0 :(得分:1)

大小为150KB的28张图像约为4MB RAM。加上应用程序数据,它不适合小堆。您可以设置large heap into manifest

android:largeHeap="true"

但是这种方法看起来像是一种解决方法,因为你有无限的内存,而且越来越多的图像可以再次出现这个错误。您还应该使用延迟加载或按设备屏幕大小调整图像大小。

答案 1 :(得分:1)

不使用时回收位图。使用查看持有者可获得更好的效果。 http://www.youtube.com/watch?v=wDBM6wVEO70。我建议你看一下链接。无论什么适用于listview也适用于gridview和视频谈论它。视频还有一个关于视图持有者的讨论,这正是你应该用来避免内存泄漏的。

还有一个关于在http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html避免内存泄漏的讨论。

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html。请参阅将缩小版本加载到内存

部分

使用MAT Analyzer检查内存泄漏。 http://www.youtube.com/watch?v=_CruQY55HOk

http://developer.android.com/training/articles/perf-tips.html处考虑一些提示。

答案 2 :(得分:0)

慢滚动的原因很简单。每次创建视图时,您都在UI线程中加载图像。您应该将加载委托给具有低优先级的另一个线程。如果您愿意,可以在UI线程中加载缩略图以快速显示内容,然后在后台加载完整分辨率。

请记住,Android有很多巧妙的技巧可以让你的应用变得更好,但你必须明智地使用它们。例如,Android在所谓的绘图缓存中缓存静态视图,但是在ImgaeViews的情况下它是没有意义的,因为它需要额外的内存并且什么都不提供。使用硬件加速UI会占用更多内存,因为每个视图缓存都是使用二次幂文本绘制的。这意味着100x35px按钮将占用128x64x4字节的额外内存。 Android也会尝试使用某种抗锯齿功能,比如线性纹理采样器 - 它很不错,但需要花费大量的CPU时间,你可能想把它关闭。

通过setImageResource加载图片几乎无法控制。您可能希望自己加载图像,以便更精确地控制装载和卸载。您也可以稍微缓存图像。 LRU缓存是为此类使用而设的类的一个很好的例子:http://developer.android.com/reference/android/util/LruCache.html。您可以加载当前图像并在左侧和右侧预加载一个图像。当用户返回上一张图像时,您将把它放在内存中。

此外,如果您想使用暴力,可以使用NativeBuffer缓存图像:http://code.google.com/p/native-buffer/。它会迫使你重新设计你的画廊,但它可以加速图像繁重的应用程序。