【问题标题】:Android : Out of memory exception while scrolling GridView?Android:滚动 GridView 时出现内存不足异常?
【发布时间】:2017-05-13 11:58:24
【问题描述】:

我创建了一个GridView 如下

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="application.example.com.fragment_practice.MainActivity"
    tools:showIn="@layout/app_bar_main">

    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/image_grid_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:columnWidth="@dimen/grid_view_width"
        android:gravity="center"
        android:horizontalSpacing="10dp"
        android:numColumns="auto_fit"
        android:stretchMode="columnWidth"
        android:verticalSpacing="@dimen/dp_10" />
</RelativeLayout>

以下是我的MainActivity.java 课程

 public class MainActivity extends Activity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      GridView gridview = (GridView) findViewById(R.id.gridview);
      gridview.setAdapter(new ImageAdapter(this));
   }
}

以下是ImageAdapter.java

   public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    // Constructor
    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) {
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(180, 180));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(15, 15, 15, 15);
        }
        else
        {
            imageView = (ImageView) convertView;
        }
        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }

    // Keep all Images in array
    public Integer[] mThumbIds = {
            R.drawable.sample_1, R.drawable.sample_2,
            R.drawable.sample_3, R.drawable.sample_4,
            R.drawable.sample_5, R.drawable.sample_6,
            R.drawable.sample_7, R.drawable.sample_8,
            R.drawable.sample_13, R.drawable.sample_9,
            R.drawable.sample_10, R.drawable.sample_11,
            R.drawable.sample_12, R.drawable.sample_13,
            R.drawable.sample_14, R.drawable.sample_16,
            R.drawable.sample_16, R.drawable.sample_17,
            R.drawable.sample_18, R.drawable.sample_19,
            R.drawable.sample_20, R.drawable.sample_21,
            R.drawable.sample_22, R.drawable.sample_23
    };
}

在我滚动之前,一切都很完美。 以下是我在上下滚动 GridView 3-4 次时遇到的异常。

致命异常:mai
进程:application.example.com.fragment_practice,PID:18917 java.lang.OutOfMemoryError:分配 4915212 字节失败 分配 2666656 个空闲字节和 2MB 直到 OOM 在 dalvik.system.VMRuntime.newNonMovableArray(本机方法) 在 android.graphics.BitmapFactory.nativeDecodeAsset(本机方法) 在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856) 在 android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675) 在 android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2230) 在 android.content.res.Resources.loadDrawableForCookie(Resources.java:4284) 在 android.content.res.Resources.loadDrawable(Resources.java:4158) 在 android.content.res.Resources.getDrawable(Resources.java:2043) 在 android.content.res.Resources.getDrawable(Resources.java:2025) 在 android.content.Context.getDrawable(Context.java:464) 在 android.widget.ImageView.resolveUri(ImageView.java:827) 在 android.widget.ImageView.setImageResource(ImageView.java:434) 在 application.example.com.fragment_practice.ImageAdapter.getView(ImageAdapter.java:48) 在 android.widget.AbsListView.obtainView(AbsListView.java:2937) 在 android.widget.GridView.makeAndAddView(GridView.java:1463) 在 android.widget.GridView.makeRow(GridView.java:366) 在 android.widget.GridView.fillUp(GridView.java:407) 在 android.widget.GridView.fillGap(GridView.java:282) 在 android.widget.AbsListView.trackMotionScroll(AbsListView.java:7307) 在 android.widget.AbsListView.scrollIfNeeded(AbsListView.java:4400) 在 android.widget.AbsListView.onTouchMove(AbsListView.java:5796) 在 android.widget.AbsListView.onTouchEvent(AbsListView.java:5624) 在 android.view.View.dispatchTouchEvent(View.java:10011) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2833) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2504) 在 android.widget.AbsListView.dispatchTouchEvent(AbsListView.java:5561) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2844) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2519) 在 com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2840) 在 com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1853) 在 android.app.Activity.dispatchTouchEvent(Activity.java:3061) 在 android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:63) 在 android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:63) 在 com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2801) 在 android.view.View.dispatchPointerEvent(View.java:10246) 在 android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5447) 在 android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5283) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4721) 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.

编辑 1: 任何人请解释为什么我在不加载时上下滚动 3-4 次网格视图时遇到此问题?

【问题讨论】:

  • 图片很大,所以会出现这个错误
  • 如果图像很大,那么它应该在创建网格视图时给出异常
  • 嘿,我不是在处理位图。我正在使用一些 54 kb 的简单 .png 图像
  • 我认为您应该尝试使用适配器支架模式。我会试着写一个答案

标签: android gridview out-of-memory android-gridview


【解决方案1】:

使用 Glide 加载图片:-

在你的 gradle 中添加依赖

compile 'com.github.bumptech.glide:glide:3.7.0'    

加载图片:-

Glide.with(mContext).load(mThumbIds[position]).placeholder(R.drawable.user_placeholder).into(imageView);

如果这不起作用,试试这个, 在 android 块中添加您应用的 build.gradle

dexOptions {
    incremental true
    javaMaxHeapSize "4g"
    jumboMode = true
}

【讨论】:

    【解决方案2】:

    我建议你使用一个名为 Glide 的库,要使用这个库,请在你的 gradle 文件中添加以下内容

    dependencies {
      compile 'com.github.bumptech.glide:glide:3.7.0'
    }
    

    然后在您的 res 文件夹中创建一个名为 drawable-nodpi 的文件夹。把你所有的图片放在那里,不要忘记从drawable-hdpi 和其他可绘制文件夹中删除你的图片。确保图像仅存在于drawable-nodpi 文件夹中。然后代替 imageView.setImageResource(mThumbIds[position]); this ,执行以下操作

    Glide.with(mContext)
         .load(mThumbIds[position])
         .diskCacheStrategy( DiskCacheStrategy.NONE )
         .skipMemoryCache( true )
         .int‌​o(imageView);
    

    让我知道它是否有效。

    【讨论】:

    • 会尽力让你知道
    • 嘿,它按预期工作,但是当我开始滚动时,我会在控制台 application.example.com.fragment_practice W/Bitmap 上收到警告:在正在使用的位图上调用重新配置!这可能会导致图形损坏!
    • 我需要更多解释,为什么你告诉创建文件夹名称drawable-nodpi,因为它与drawable-hdpi 一起工作正常?有什么原因吗?
    • 对于位图,您可以尝试 asBitmap()‌ 属性像 Glide.with(mContext) .load(mThumbIds[position]) .asBitmap()‌ .diskCacheStrategy( DiskCacheStrategy.NONE ) .skipMemoryCache( true ) .int‌​o(imageView);是的,使用drawable-nodpi是有原因的,由于将图像采样到设备大小而发生内存不足错误。通过使用 drawable-nodpi,您可以根据设备 dpi 停止缩放。
    • 我接受了你的回答,但添加 asBitmap() 并不能解决该警告
    猜你喜欢
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多