Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

We are getting Out of memory exceptions in firebase #2057

Closed
geek2driod opened this issue Feb 23, 2018 · 7 comments
Closed

We are getting Out of memory exceptions in firebase #2057

geek2driod opened this issue Feb 23, 2018 · 7 comments

Comments

@geek2driod
Copy link

Hello, We switch image caching library from Glide to Fresco. Fresco is much better then Glide but unfortunately we are getting out of memory exceptions in our Firebase crash reporting console.
Please guide us how to resolve this exception:

Exception java.lang.OutOfMemoryError: Failed to allocate a 391260 byte allocation with 239306 free bytes and 233KB until OOM
dalvik.system.VMRuntime.newNonMovableArray (VMRuntime.java)
android.graphics.Bitmap.nativeCreate (Bitmap.java)
android.graphics.Bitmap.createBitmap (Bitmap.java:942)
android.graphics.Bitmap.createBitmap (Bitmap.java:913)
android.graphics.Bitmap.createBitmap (Bitmap.java:880)
com.facebook.imagepipeline.memory.BitmapPool.h ()
com.facebook.imagepipeline.memory.BitmapPool.a ()
com.facebook.imagepipeline.memory.BasePool.get ()
com.facebook.imagepipeline.bitmaps.ArtBitmapFactory.createBitmapInternal ()
com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory.createBitmap ()
com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory.createBitmap ()
com.facebook.fresco.animation.bitmap.BitmapAnimationBackend.drawFrameOrFallback ()
com.facebook.fresco.animation.bitmap.BitmapAnimationBackend.drawFrameOrFallback ()
com.facebook.fresco.animation.bitmap.BitmapAnimationBackend.drawFrameOrFallback ()
com.facebook.fresco.animation.bitmap.BitmapAnimationBackend.drawFrame ()
com.facebook.fresco.animation.backend.AnimationBackendDelegate.drawFrame ()
com.facebook.fresco.animation.backend.AnimationBackendDelegateWithInactivityCheck.drawFrame ()
com.facebook.fresco.animation.drawable.AnimatedDrawable2.draw ()
com.facebook.drawee.drawable.ForwardingDrawable.draw ()
com.facebook.drawee.drawable.ForwardingDrawable.draw ()
com.facebook.drawee.drawable.ScaleTypeDrawable.draw ()
com.facebook.drawee.drawable.FadeDrawable.drawDrawableWithAlpha ()
com.facebook.drawee.drawable.FadeDrawable.draw ()
com.facebook.drawee.drawable.ForwardingDrawable.draw ()
com.facebook.drawee.generic.RootDrawable.draw ()
android.widget.ImageView.onDraw (ImageView.java:1179)
android.view.View.draw (View.java:16486)
android.view.View.updateDisplayListIfDirty (View.java:15416)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)
android.view.View.getDisplayList (View.java:15438)
android.view.ViewGroup.recreateChildDisplayList (ViewGroup.java:3697)
android.view.ViewGroup.dispatchGetDisplayList (ViewGroup.java:3676)
android.view.View.updateDisplayListIfDirty (View.java:15376)

@erikandre
Copy link
Contributor

Hi @geek2driod ,

Sorry for the slow response, there are some general things you can check to help reduce the number of OutOfMemoryErrors you get.

  • Verify that all images you load have a suitable size (something close to the size you want to display on the screen).
  • If you don't have control over the exact size of the images you load, then make sure that you specify resize options when loading the image. This will reduce memory usage: http://frescolib.org/docs/resizing.html
  • If you are using the image pipeline directly to load images (and get the bitmap), be careful so that you don't leak any memory.

@geek2driod
Copy link
Author

Hello @erikandre

Thanks for your response. We are using fresco in RecyclerView and in custom views.
Following code is written in RecyclerView adapter:

`private void setupImage(final SimpleDraweeView simpleDraweeView, final Uri uri) {
simpleDraweeView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@OverRide
public boolean onPreDraw() {
try {
if (simpleDraweeView != null) {
simpleDraweeView.getViewTreeObserver().removeOnPreDrawListener(this);
float width = simpleDraweeView.getWidth();
float height = simpleDraweeView.getHeight();

                    if (width <= 0)
                        width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics());

                    if (height <= 0) {
                        width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200, getResources().getDisplayMetrics());
                    }
                    ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                            .setResizeOptions(new ResizeOptions((int) width, (int) height))
                            .build();
                    PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                            .setOldController(simpleDraweeView.getController())
                            .setImageRequest(request)
                            .build();
                    simpleDraweeView.setController(controller);
                }
            } catch (Exception e){
                e.printStackTrace();
            }
            return true;
        }
    });
}`

Following code is written in custom views:

`ImageRequest imageRequest = ImageRequest.fromUri(url);
ImagePipeline imagePipeline = Fresco.getImagePipeline();
final DataSource<CloseableReference> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
dataSource.subscribe(
new BaseBitmapDataSubscriber() {

                    @Override
                    protected void onNewResultImpl(Bitmap bitmap) {
                        try {
                            setTeam2Flag(bitmap);
                            if(dataSource!=null && !dataSource.isClosed()) {
                                dataSource.close();
                            }
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }

                    @Override
                    protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                        // In general, failing to fetch the image should not keep us from displaying the
                        // notification. We proceed without the bitmap.
                        if(dataSource!=null && !dataSource.isClosed()) {
                            dataSource.close();
                        }
                    }
                },
                UiThreadImmediateExecutorService.getInstance());`

That's the only code snippet of fresco we are using in our whole app. Please guide us that the above code is right or wrong.
Thanks

@erikandre
Copy link
Contributor

In the layout for your recyclerView items, how do you define the width and height of the SimpleDraweeView?

Also, what does setTeam2Flag(bitmap) do?

@geek2driod
Copy link
Author

geek2driod commented Mar 15, 2018

Hello @erikandre ,

I am defining SimpleDraweeView in my RecyclerView items layout as follows:

<com.facebook.drawee.view.SimpleDraweeView
android:layout_width="match_parent"
android:layout_height="200dp"
app:viewAspectRatio="1.33"
android:background="@color/greylight"
app:progressBarImage="@mipmap/notificationicon"
fresco:progressBarImageScaleType="centerInside"
app:progressBarAutoRotateInterval="1500"/>

setTeam2Flag method is used to keep the WeakReference of bitmap and invalidate the custom view. Following is the code snippet of this method:

public void setTeam2Flag(final Bitmap bitmap){
if(bitmap != null) {
this.flag2 = new WeakReference<Bitmap>(bitmap);
flag2Loaded = true;
this.invalidate();
}
}

Thanks,

@erikandre
Copy link
Contributor

Since you have a fixed hight and aspect ratio, could you not set the resize option without the need to the layout listener?

The usage of com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber is not correct (but I don't think it could case the issue you're experiencing). If you check the documentation for BaseBitmapDataSubscriber, you will see that is says

public void onNewResultImpl(@Nullable Bitmap bitmap) { // Pass bitmap to system, which makes a copy of the bitmap. updateStatus(bitmap); // No need to do any cleanup. }

I recommend that you either switch to using a BaseDataSubscriber and manage the ClosableReference or keep using BaseBitmapDataSubscriber and instead copy the bitmap.

@geek2driod
Copy link
Author

geek2driod commented Mar 15, 2018

@erikandre Thankyou for your suggestions. I have changed my code as you said. I hope these changes will reduces the Out of memory exceptions.

@oprisnik
Copy link
Contributor

Seems like this has been fixed. If not, please let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants