Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Out Of Memory Error When loading more images in Glide

Edited:

  • In my application, I am loading more than 300 images in home page. I used glide to load images. I'm getting Out of Memory Error.

I have used large heap true in manifest :

android:largeHeap="true"

Glide Version:

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

Device/Android Version:

Nexus Device 6.0 version

Every images I'm getting from Json would be 800kb to 1mb.

activity_layout:

<RelativeLayout
    android:id="@+id/home_layout_bottom"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/home_layout_top_recycler"
    android:layout_margin="5dp">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_list_tab_home_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:scrollbars="vertical"
        android:visibility="visible" />

    <TextView
        android:id="@+id/no_user_posts_item_tv_recycler"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/rv_list_tab_home_recycler"
        android:layout_marginTop="80dp"
        android:layout_centerHorizontal="true"
        android:text="@string/txt_no_posts_available"
        android:textColor="@color/txt_common_black"
        android:textSize="@dimen/txt_size" />
</RelativeLayout>

adapter code:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;

    final HomePostItems rowItem = getItem(position);

    LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    if (convertView == null) {

        convertView = mInflater.inflate(R.layout.lv_adapter_post_items_layout, null);

      holder = new ViewHolder();

      holder.ivPostedImage = (ImageView) convertView.findViewById(R.id.iv_posted_img);


        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

      ..................

          Glide.with(context).load(rowItem.getPosteduserpostimage())
                        .placeholder(R.drawable.golive_load_image).error(R.drawable.golive_cancel_image)
                        .override(600, 200)
                        .into(holder.ivPostedImage);

adapter_layout.xml:

<RelativeLayout
    android:id="@+id/rl_lv_user_post_adapter_img_holder_home"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:layout_marginLeft="1dp"
    android:layout_marginRight="1dp"
    android:layout_below="@+id/tv_user_posted_msg_post_items_home" >

    <ImageView
        android:id="@+id/iv_posted_img_home"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:scaleType="fitXY"
        android:background="#ffffff"
        android:contentDescription="@string/cont_desc"/>
</RelativeLayout>

Logcat:

Request threw uncaught throwable
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Failed to allocate a 6365196 byte allocation with 865912 free bytes and 845KB until OOM
at java.util.concurrent.FutureTask.report(FutureTask.java:94)
at java.util.concurrent.FutureTask.get(FutureTask.java:164)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor.afterExecute(FifoPriorityThreadPoolExecutor.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1121)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 6365196 byte allocation with 865912 free bytes and 845KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:635)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:611)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeStream(Downsampler.java:329)
at com.bumptech.glide.load.resource.bitmap.Downsampler.downsampleWithSize(Downsampler.java:220)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:153)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:50)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:19)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:39)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:20)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeBitmapWrapper(GifBitmapWrapperResourceDecoder.java:121)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeStream(GifBitmapWrapperResourceDecoder.java:94)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:71)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:61)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:22)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromSourceData(DecodeJob.java:190)
at com.bumptech.glide.load.engine.DecodeJob.decodeSource(DecodeJob.java:177)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromSource(DecodeJob.java:128)
at com.bumptech.glide.load.engine.EngineRunnable.decodeFromSource(EngineRunnable.java:122)
at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:101)
at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at java.lang.Thread.run(Thread.java:818) 
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)

I don't know how to fix this OOM issue. Please share your suggestion, if you have already familiar with this issue.

like image 622
Steve Avatar asked Jul 25 '16 05:07

Steve


2 Answers

  • I solved this issue by removing nested scroll view placed above recyclerview. Why OutOfMemory error occurred means, when loading more than 200 images in home page, it is loading all 200 images because of using nested scroll view above recyclerview.

  • So I can't check the logcat image view width and height one by one in adapter.

  • After removed nested scroll view fixed out of memory error.because it will load only 3 images displayed in device when coming to home activity.

  • Also check this, how to use scroll instead of nested scroll view.

like image 74
Steve Avatar answered Sep 18 '22 22:09

Steve


This is not an exact solution to your problem, but you need to keep these things in mind while loading images in a list using Glide.

The main threatening part of your problem is the image size. The image you're getting is almost 1mb each! Which is in fact too large for displaying them into a list having 300+ items. So if you're doing the server side too, its always recommended to have the images in several different sizes.

For example, in case of showing a friend list along with their profile pictures, I would suggest you get the whole list first from the server. Then fetch all of the profile images and store them locally. Then populate the ListView. And the most important part is while uploading a profile picture of an user to the server, after uploading it, the server needs to keep several sizes of it e.g. low, mid and high res version. So that while serving the profile picture urls for the ListView the server might provide the images with low res as they'll be used most likely for thumbnails.

Using RecyclerView instead of ListView is a good call too. But it won't solve the problem you've here when you're in a low-end device.

OMM has nothing to do with you can solve programatically. You need to resize your image to a lower res version.

You can check for the Glide's caching mechanism too. I would suggest you use the caching strategy so that every time you don't have to load the image from server.

Good luck.

like image 41
Reaz Murshed Avatar answered Sep 19 '22 22:09

Reaz Murshed