DialogFragment leaking memory
Asked Answered
V

3

8

In the app I'm working on I'm seeing a memory leak in a DialogFragment and the only way to fix it so far has been to remove all views when the DialogFragment gets destroyed, is this a normal thing to have to do? I'm working with a custom ROM so wasn't sure if maybe that has something to do with this issue. Is there any reason NOT removing all the views from the dialog would cause them to leak memory?

    @Override
    public void onDestroyView() {
        if (getView() instanceof ViewGroup) {
            ((ViewGroup)getView()).removeAllViews();
        }
        super.onDestroyView();
    }
Vinni answered 25/4, 2016 at 14:0 Comment(1)
to confirm it you should also try on non-rooted phoneCowardly
V
11

This happens to my App too and I found the leak using Leakcanary.

It happens when you have a Dialog with EditText. The Blink of the Cursor, which is implemented using a callback is not handled properly when closing the View containing the EditText. And it happens by chance according to this.

https://code.google.com/p/android/issues/detail?id=188551

Edit

And this is how what I do before every dialog.dismiss():

editText.setCursorVisible(false);
dismiss();

Hope this helps!

Vitellin answered 18/10, 2016 at 11:14 Comment(1)
Should be marked as correct answer. Fixed my issue. Thanks!Pauperize
P
4

MemoryLeak can happen for many causes, some common causes :

  • Keep reference of your object(in this case instance of your DialogFragment) in some static fields.
  • Pass Context to Thread or AsyncTask because Threads is also GC root!
  • Your class have non-static inner class, in this case memory leak happen if inner class related to GC root (for example if inner class is instance of AsyncTask).

In your case maybe you have a view that related to GC root, while that view can not be garbage collected your dialog that keep views also can not be garbage collected.

Phalanstery answered 25/4, 2016 at 14:33 Comment(0)
T
0

My occurrence may have nothing to do with your experience, but it did have to do with capturing user input from an EditText widget in a DialogFragment and sending it to the calling Fragment with a Callback. Leakcanary gave me the following message:

====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS

References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.

99628 bytes retained by leaking objects
Signature: d189c386cd77f5b37c0a05eb1a290629edee
┬───
│ GC Root: System class
│
├─ com.example.jbiss.petminder.dialogs.DurationDialogFragment class
│    Leaking: NO (a class is never leaking)
│    ↓ static DurationDialogFragment.mCallback
│                                    ~~~~~~~~~
╰→ com.example.jbiss.petminder.fragments.ScheduleAppointmentFragment instance
Leaking: YES (ObjectWatcher was watching this because             
com.example.jbiss.petminder.fragments.ScheduleAppointmentFragment received         
Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
key = 820c4d81-c97f-412b-be14-4cc17f883313
watchDurationMillis = 5169
retainedDurationMillis = 168
key = 2b74e5f3-c55c-4797-9d7a-dd2bca477a53

It turns out that it was due to me declaring mCallback as static. When I deleted "static" from the declaration, then I'd get this message for one of the other DialogFragment's mCallback. Well, I figured it out and deleted "static" from all of those mCallback declarations and no more leak, at least from that. I don't know why I did that, but I did and leakcanary found it for me and saved me grief going forward.

Titograd answered 25/2, 2020 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.