Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile...

148
Nuking nasty memory leaks Pierre-Yves Ricau LeakCanary

Transcript of Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile...

Page 1: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

Nuking nasty memory leaks

Pierre-Yves Ricau

LeakCanary

Page 2: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

Pierre-Yves Ricau

Page 3: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 4: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 5: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 6: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 7: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 8: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

dependencies {}A

Page 9: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'}A

Page 10: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); }A }B

Page 11: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); if (LeakCanary.isInAnalyzerProcess(this)) { return; } LeakCanary.install(this); }A }B

Page 12: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 13: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 14: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 15: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 16: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb)); }A @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Application app = (Application) getContext().getApplicationContext(); app.registerActivityLifecycleCallbacks(new LifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { animate().alpha(1); }B @Override public void onActivityPaused(Activity activity) { animate().alpha(0); }C }); }D }E

Page 17: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb)); }A @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Application app = (Application) getContext().getApplicationContext(); app.registerActivityLifecycleCallbacks(new LifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { animate().alpha(1); }B @Override public void onActivityPaused(Activity activity) { animate().alpha(0); }C }); }D }E

Page 18: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb)); }A @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Application app = (Application) getContext().getApplicationContext(); app.registerActivityLifecycleCallbacks(new LifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { animate().alpha(1); }B @Override public void onActivityPaused(Activity activity) { animate().alpha(0); }C }); }D }E

Page 19: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb)); }A @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Application app = (Application) getContext().getApplicationContext(); app.registerActivityLifecycleCallbacks(new LifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { animate().alpha(1); }B @Override public void onActivityPaused(Activity activity) { animate().alpha(0); }C }); }D }E

Page 20: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb)); }A @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Application app = (Application) getContext().getApplicationContext(); app.registerActivityLifecycleCallbacks(new LifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { animate().alpha(1); }B @Override public void onActivityPaused(Activity activity) { animate().alpha(0); }C }); }D }E private LifecycleCallbacks callbacks; private final Application app;

Page 21: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { private LifecycleCallbacks callbacks; private final Application app; public NeoMobRealismView(Context context, AttributeSet attrs) {…} @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); callbacks = new LifecycleCallbacks() {…}; app.registerActivityLifecycleCallbacks(callbacks); }D @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); app.unregisterActivityLifecycleCallbacks(callbacks); }F }E

Page 22: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 23: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 24: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 25: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 26: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

Page 27: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

Page 28: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

class C {}

Page 29: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

class C {}

static void triumvirate() { A a = new A(); }

Page 30: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

class C {}

static void triumvirate() { A a = new A(); }

Page 31: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

class C {}

static void triumvirate() { A a = new A(); }B

Page 32: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

class C {}

static void triumvirate() { A a = new A(); B b = new B(); }B

Page 33: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A {}

class B {}

class C {}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); }B

Page 34: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b; }

class B {}

class C {}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C();}B

Page 35: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c; }

class C {}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C();}

Page 36: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a; }

static void triumvirate() { A a = new A(); B b = new B(); C c = new C();}

Page 37: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b; }

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; }

Page 38: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c; }

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; }

Page 39: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a; }

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a; }

Page 40: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a; }

Page 41: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a; }

Page 42: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a; }

Page 43: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a;}

static A singleton

Page 44: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a; singleton = a; }

static A singleton

Page 45: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class A { B b;}

class B { C c;}

class C { A a;}

static void triumvirate() { A a = new A(); B b = new B(); C c = new C(); a.b = b; b.c = c; c.a = a; singleton = a; }

static A singleton

Page 46: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 47: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 48: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 49: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 50: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class Activity { boolean mDestroyed = true;}

Page 51: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 52: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 53: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 54: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 55: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 56: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 57: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 58: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 59: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 60: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 61: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb)); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Application app = (Application) getContext().getApplicationContext(); app.registerActivityLifecycleCallbacks(new LifecycleCallbacks() { @Override public void onActivityResumed(Activity activity) { animate().alpha(1); } @Override public void onActivityPaused(Activity activity) { animate().alpha(0); } }); }}

Page 62: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class NeoMobRealismView$1 extends LifecycleCallbacks { private final NeoMobRealismView this$0; public NeoMobRealismView$1(NeoMobRealismView this$0) { this.this$0 = this$0; } @Override public void onActivityResumed(Activity activity) { this$0.animate().alpha(1); } @Override public void onActivityPaused(Activity activity) { this$0.animate().alpha(0); } } public class NeoMobRealismView extends View { public NeoMobRealismView(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(getResources().getColor(R.color.ikb));

Page 63: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 64: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 65: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 66: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 67: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 68: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 69: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

In com.example.leakcanary:1.0:1. * com.example.leakcanary.MainActivity has leaked: * GC ROOT static android.app.ActivityThread.sCurrentActivityThread * references android.app.ActivityThread.mInitialApplication * references com.example.leakcanary.ExampleApplication.mActivityLifecycleCallbacks * references java.util.ArrayList.elementData * references array java.lang.Object[].[5] * references com.example.leakcanary.NeoMobRealismView$1.this$0 (anonymous subclass of com.example.leakcanary.ActivityLifecycleCallbacksAdapter) * references com.example.leakcanary.NeoMobRealismView.mContext * leaks com.example.leakcanary.MainActivity instance * Retaining: 673 B. * Reference Key: 8b2e09ef-1ea7-48da-b09e-7bf337f64473 * Device: LGE google Nexus 5X bullhead * Android Version: 7.0 API: 24 LeakCanary: 1.6-SNAPSHOT 050b554 * Durations: watch=1296983ms, gc=210ms, heap dump=33311ms, analysis=125485ms

* Details: * Class android.app.ActivityThread | static DEBUG_BROADCAST = false | static TWO_COUNT_COLUMNS = java.lang.String@1873829608 (0x6fb05ee8) | static sCurrentActivityThread = android.app.ActivityThread@851460352 (0x32c04100) | static DEBUG_BACKUP = false

Page 70: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

* Details: * Class android.app.ActivityThread | static DEBUG_BROADCAST = false | static TWO_COUNT_COLUMNS = java.lang.String@1873829608 (0x6fb05ee8) | static sCurrentActivityThread = android.app.ActivityThread@851460352 (0x32c04100) | static DEBUG_BACKUP = false | static LOG_AM_ON_RESUME_CALLED = 30022 | static DEBUG_RESULTS = false | static LOG_AM_ON_STOP_CALLED = 30049 | static ONE_COUNT_COLUMN_HEADER = java.lang.String@1873816328 (0x6fb02b08) | static DEBUG_ORDER = false | static sPackageManager = android.content.pm.IPackageManager$Stub$Proxy@851448320 (0x32c01200) | static THUMBNAIL_FORMAT = android.graphics.Bitmap$Config@1879418296 (0x7005a5b8) | static SERVICE_DONE_EXECUTING_START = 1 | static REPORT_TO_ACTIVITY = true | static DEBUG_MEMORY_TRIM = false | static ACTIVITY_THREAD_CHECKIN_VERSION = 4 | static HEAP_COLUMN = java.lang.String@1873840320 (0x6fb088c0) | static $classOverhead = byte[1223]@1879556985 (0x7007c379) | static SERVICE_DONE_EXECUTING_STOP = 2 | static HEAP_FULL_COLUMN = java.lang.String@1873843888 (0x6fb096b0) | static SERVICE_DONE_EXECUTING_ANON = 0

Page 71: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

| [14] = null * Instance of com.example.leakcanary.NeoMobRealismView$1 | static $classOverhead = byte[664]@851688449 (0x32c3bc01) | this$0 = com.example.leakcanary.NeoMobRealismView@852252560 (0x32cc5790) | shadow$_klass_ = com.example.leakcanary.NeoMobRealismView$1 | shadow$_monitor_ = 0 * Instance of com.example.leakcanary.NeoMobRealismView | static $classOverhead = byte[6184]@851804161 (0x32c58001) | mAccessibilityCursorPosition = -1 | mAccessibilityDelegate = null | mAccessibilityTraversalAfterId = -1 | mAccessibilityTraversalBeforeId = -1 | mAccessibilityViewId = -1 | mAnimator = android.view.ViewPropertyAnimator@852248440 (0x32cc4778) | mAttachInfo = null | mAttributes = null | mBackground = android.graphics.drawable.ColorDrawable@852305184 (0x32cd2520) | mBackgroundRenderNode = android.view.RenderNode@852339848 (0x32cdac88) | mBackgroundResource = 0 | mBackgroundSizeChanged = false | mBackgroundTint = null | mBottom = 1098 | mCachingFailed = false | mClipBounds = null

Page 72: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

| [14] = null * Instance of com.example.leakcanary.NeoMobRealismView$1 | static $classOverhead = byte[664]@851688449 (0x32c3bc01) | this$0 = com.example.leakcanary.NeoMobRealismView@852252560 (0x32cc5790) | shadow$_klass_ = com.example.leakcanary.NeoMobRealismView$1 | shadow$_monitor_ = 0 * Instance of com.example.leakcanary.NeoMobRealismView | static $classOverhead = byte[6184]@851804161 (0x32c58001) | mAccessibilityCursorPosition = -1 | mAccessibilityDelegate = null | mAccessibilityTraversalAfterId = -1 | mAccessibilityTraversalBeforeId = -1 | mAccessibilityViewId = -1 | mAnimator = android.view.ViewPropertyAnimator@852248440 (0x32cc4778) | mAttachInfo = null | mAttributes = null | mBackground = android.graphics.drawable.ColorDrawable@852305184 (0x32cd2520) | mBackgroundRenderNode = android.view.RenderNode@852339848 (0x32cdac88) | mBackgroundResource = 0 | mBackgroundSizeChanged = false | mBackgroundTint = null | mBottom = 1098 | mCachingFailed = false | mClipBounds = null

Page 73: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class View { AttachInfo mAttachInfo; public boolean isAttachedToWindow() { return mAttachInfo != null; }

}

Page 74: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 75: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 76: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 77: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 78: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

StackTraceElement[] stackTrace = { new StackTraceElement("com.foo.Foo", "bakeBaguette", "Foo.java", 42), new StackTraceElement("com.foo.Bar", "bailarLaBamba", "Bar.java", 7), }; RuntimeException exception = new RuntimeException(); exception.setStackTrace(stackTrace);

Page 79: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class BugsnagLeakUploader { public BugsnagLeakUploader() {…} public void uploadLeak(AnalysisResult result, String leakInfo) { Throwable t = exception(result.className, result.leakTrace); bugsnagClient.notify(t, Severity.WARNING, metadata); } private RuntimeException exception(String className, LeakTrace trace) {…} }

Page 80: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 81: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 82: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 83: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 84: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 85: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final class RunQueue { private final ArrayList<HandlerAction> mActions = new ArrayList<>();

void post(Runnable action) { postDelayed(action, 0); }A void postDelayed(Runnable action, long delayMillis) { HandlerAction handlerAction = new HandlerAction(); handlerAction.action = action; handlerAction.delay = delayMillis; synchronized (mActions) { mActions.add(handlerAction); }B }C }D }E

Page 86: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final class RunQueue { private final ArrayList<HandlerAction> mActions = new ArrayList<>();

void post(Runnable action) { postDelayed(action, 0); }A void postDelayed(Runnable action, long delayMillis) { HandlerAction handlerAction = new HandlerAction(); handlerAction.action = action; handlerAction.delay = delayMillis; synchronized (mActions) { mActions.add(handlerAction); }B }C }D }E

Page 87: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final class RunQueue { private final ArrayList<HandlerAction> mActions = new ArrayList<>();

void post(Runnable action) { postDelayed(action, 0); }A void postDelayed(Runnable action, long delayMillis) { HandlerAction handlerAction = new HandlerAction(); handlerAction.action = action; handlerAction.delay = delayMillis; synchronized (mActions) { mActions.add(handlerAction); }B }C }D }E

Page 88: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final class RunQueue { private final ArrayList<HandlerAction> mActions = new ArrayList<>();

void post(Runnable action) { postDelayed(action, 0); }A void postDelayed(Runnable action, long delayMillis) { HandlerAction handlerAction = new HandlerAction(); handlerAction.action = action; handlerAction.delay = delayMillis; synchronized (mActions) { mActions.add(handlerAction); }B }C }D }EE

Page 89: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { /** * The run queue is used to enqueue pending work from Views when no Handler * is attached. The work is executed during the next call to * performTraversals on the thread. */ static final class RunQueue { private final ArrayList<HandlerAction> mActions = new ArrayList<>();

void post(Runnable action) { postDelayed(action, 0); }A void postDelayed(Runnable action, long delayMillis) { HandlerAction handlerAction = new HandlerAction(); handlerAction.action = action; handlerAction.delay = delayMillis; synchronized (mActions) { mActions.add(handlerAction); }B }C

Page 90: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { /** * The run queue is used to enqueue pending work from Views when no Handler * is attached. The work is executed during the next call to * performTraversals on the thread. */ static final class RunQueue { private final ArrayList<HandlerAction> mActions = new ArrayList<>();

void post(Runnable action) { postDelayed(action, 0); }A void postDelayed(Runnable action, long delayMillis) { HandlerAction handlerAction = new HandlerAction(); handlerAction.action = action; handlerAction.delay = delayMillis; synchronized (mActions) { mActions.add(handlerAction); }B }C

Page 91: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class View { public void postOnAnimation(Runnable action) { AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { attachInfo.mViewRootImpl.mChoreographer.postCallback( Choreographer.CALLBACK_ANIMATION, action, null); } else { ViewRootImpl.getRunQueue().post(action); }A }B

public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); }E ViewRootImpl.getRunQueue().post(action); return true; }C }D

Page 92: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class View { public void postOnAnimation(Runnable action) { AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { attachInfo.mViewRootImpl.mChoreographer.postCallback( Choreographer.CALLBACK_ANIMATION, action, null); } else { ViewRootImpl.getRunQueue().post(action); }A }B

public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); }E ViewRootImpl.getRunQueue().post(action); return true; }C }D

Page 93: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class View { public void postOnAnimation(Runnable action) { AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { attachInfo.mViewRootImpl.mChoreographer.postCallback( Choreographer.CALLBACK_ANIMATION, action, null); } else { ViewRootImpl.getRunQueue().post(action); }A }B

public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); }E ViewRootImpl.getRunQueue().post(action); return true; }C }D

Page 94: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class View { public void postOnAnimation(Runnable action) { AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { attachInfo.mViewRootImpl.mChoreographer.postCallback( Choreographer.CALLBACK_ANIMATION, action, null); } else { ViewRootImpl.getRunQueue().post(action); }A }B

public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); }E ViewRootImpl.getRunQueue().post(action); return true; }C }D

Page 95: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>();

static RunQueue getRunQueue() { RunQueue queue = sRunQueues.get(); if (queue != null) { return queue; }A queue = new RunQueue(); sRunQueues.set(queue); return queue; }B }C

Page 96: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>();

static RunQueue getRunQueue() { RunQueue queue = sRunQueues.get(); if (queue != null) { return queue; }A queue = new RunQueue(); sRunQueues.set(queue); return queue; }B }C

Page 97: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>();

static RunQueue getRunQueue() { RunQueue queue = sRunQueues.get(); if (queue != null) { return queue; }A queue = new RunQueue(); sRunQueues.set(queue); return queue; }B }C

Page 98: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public final class ViewRootImpl { static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<>();

static RunQueue getRunQueue() { RunQueue queue = sRunQueues.get(); if (queue != null) { return queue; }A queue = new RunQueue(); sRunQueues.set(queue); return queue; }B }C

Page 99: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 100: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 101: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 102: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 103: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class AppCompatActivity extends FragmentActivity {

private AppCompatDelegate mDelegate;

@Override protected void onDestroy() { super.onDestroy(); getDelegate().onDestroy(); }

public AppCompatDelegate getDelegate() { if (mDelegate == null) { mDelegate = AppCompatDelegate.create(this, this); } return mDelegate; } }

Page 104: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 105: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 106: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 107: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class AppCompatDelegateImplV9 {

private final Runnable mInvalidatePanelMenuRunnable = new Runnable() { @Override public void run() {…} };

private void invalidatePanelMenu(int featureId) { mWindowDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } }

Page 108: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class AppCompatDelegateImplV9 {

private final Runnable mInvalidatePanelMenuRunnable = new Runnable() { @Override public void run() {…} };

private void invalidatePanelMenu(int featureId) { mWindowDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } }

Page 109: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

class AppCompatDelegateImplV9 {

private final Runnable mInvalidatePanelMenuRunnable = new Runnable() { @Override public void run() {…} };

private void invalidatePanelMenu(int featureId) { mWindowDecor.postOnAnimation(mInvalidatePanelMenuRunnable); }

@Override public void onDestroy() { super.onDestroy(); mWindowDecor.removeCallbacks(mInvalidatePanelMenuRunnable); }

Page 110: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 111: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 112: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 113: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 114: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

* Instance of com.squareup.ui.permissions.PasscodeUnlockView | mAccessibilityCursorPosition = -1 | mAccessibilityDelegate = null | mAccessibilityTraversalAfterId = -1 | mAccessibilityTraversalBeforeId = -1 | mAccessibilityViewId = -1 | mAnimator = null | mAttachInfo = null | mAttributes = null | mBackground = android.graphics.drawable.ColorDrawable@328049760 (0x138da460) | mBackgroundRenderNode = android.view.RenderNode@338685248 (0x142fed40) | mBackgroundResource = 0 | mBackgroundSizeChanged = false | mBackgroundTint = null | mBottom = 1731 | mCachingFailed = false | mClipBounds = null | mContentDescription = null

Page 115: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

* Instance of com.squareup.ui.permissions.PasscodeUnlockView | mAccessibilityCursorPosition = -1 | mAccessibilityDelegate = null | mAccessibilityTraversalAfterId = -1 | mAccessibilityTraversalBeforeId = -1 | mAccessibilityViewId = -1 | mAnimator = null | mAttachInfo = null | mAttributes = null | mBackground = android.graphics.drawable.ColorDrawable@328049760 (0x138da460) | mBackgroundRenderNode = android.view.RenderNode@338685248 (0x142fed40) | mBackgroundResource = 0 | mBackgroundSizeChanged = false | mBackgroundTint = null | mBottom = 1731 | mCachingFailed = false | mClipBounds = null | mContentDescription = null

Page 116: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 117: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 118: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 119: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class PasscodeUnlockView extends FrameLayout {

void setBackgroundImage(final RequestCreator request) { Views.waitForMeasure(merchantImage, new Views.OnMeasuredCallback() { @Override public void onMeasured(View view, int width, int height) { request.into(merchantImage, new Callback() { @Override public void onSuccess() {…} @Override public void onError() {…} }); } }); } }

Page 120: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class PasscodeUnlockView extends FrameLayout {

void setBackgroundImage(final RequestCreator request) { Views.waitForMeasure(merchantImage, new Views.OnMeasuredCallback() { @Override public void onMeasured(View view, int width, int height) { request.into(merchantImage, new Callback() { @Override public void onSuccess() {…} @Override public void onError() {…} }); } }); } }

Page 121: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 122: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 123: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 124: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 125: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class PasscodeUnlockView extends FrameLayout {

@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); picasso.cancelRequest(merchantImage); } }

Page 126: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class Picasso {

final Map<Object, Action> targetToAction;

public void cancelRequest(ImageView target) { Action action = targetToAction.remove(target); if (action != null) { action.cancel(); dispatcher.dispatchCancel(action); } if (target instanceof ImageView) {…} } }

Page 127: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class Picasso {

final Map<Object, Action> targetToAction;

public void cancelRequest(ImageView target) { Action action = targetToAction.remove(target); if (action != null) { action.cancel(); dispatcher.dispatchCancel(action); } if (target instanceof ImageView) {…} } }

Page 128: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class Picasso {

final Map<Object, Action> targetToAction;

public void cancelRequest(ImageView target) { Action action = targetToAction.remove(target); if (action != null) { action.cancel(); dispatcher.dispatchCancel(action); } if (target instanceof ImageView) {…} } }

Page 129: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

abstract class Action<T> {

boolean cancelled;

void cancel() { cancelled = true; }

}

Page 130: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

* Instance of com.squareup.picasso.ImageViewAction | callback = com.squareup.ui.permissions.PasscodeUnlockView$4$1@338661168 (0x142f8f30) | cancelled = false | errorDrawable = null | errorResId = 0 | key = java.lang.String@316241360 (0x12d975d0) | memoryPolicy = 0 | networkPolicy = 0 | noFade = false | picasso = com.squareup.picasso.Picasso@333016576 (0x13d96e00) | request = com.squareup.picasso.Request@338645408 (0x142f51a0) | tag = com.squareup.picasso.ImageViewAction@338500224 (0x142d1a80) | target = com.squareup.picasso.Action$RequestWeakReference@338684128 (0x142fe8e0) | willReplay = false | shadow$_klass_ = com.squareup.picasso.ImageViewAction | shadow$_monitor_ = -2047389420

Page 131: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

* Instance of com.squareup.picasso.ImageViewAction | callback = com.squareup.ui.permissions.PasscodeUnlockView$4$1@338661168 (0x142f8f30) | cancelled = false | errorDrawable = null | errorResId = 0 | key = java.lang.String@316241360 (0x12d975d0) | memoryPolicy = 0 | networkPolicy = 0 | noFade = false | picasso = com.squareup.picasso.Picasso@333016576 (0x13d96e00) | request = com.squareup.picasso.Request@338645408 (0x142f51a0) | tag = com.squareup.picasso.ImageViewAction@338500224 (0x142d1a80) | target = com.squareup.picasso.Action$RequestWeakReference@338684128 (0x142fe8e0) | willReplay = false | shadow$_klass_ = com.squareup.picasso.ImageViewAction | shadow$_monitor_ = -2047389420

Page 132: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 133: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 134: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 135: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public interface SlackApi { @Multipart @POST("/api/files.upload") UploadFileResponse uploadFile( @Part("token") String token, @Part("file") TypedFile file, @Part("filetype") String filetype, @Part("filename") String filename, @Part("title") String title, @Part("initial_comment") String initialComment, @Part("channels") String channels ); }

Page 136: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 137: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class Picasso {

final Map<Object, Action> targetToAction;

public void cancelRequest(ImageView target) { Action action = targetToAction.remove(target); if (action != null) { action.cancel(); dispatcher.dispatchCancel(action); } if (target instanceof ImageView) {…} } }

Page 138: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 139: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 140: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 141: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class PasscodeUnlockView extends FrameLayout {

@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); picasso.cancelRequest(merchantImage); } }

Page 142: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 143: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

public class PasscodeUnlockView extends FrameLayout {

void setBackgroundImage(final RequestCreator request) { Views.waitForMeasure(merchantImage, new Views.OnMeasuredCallback() { @Override public void onMeasured(View view, int width, int height) { request.into(merchantImage, new Callback() { @Override public void onSuccess() {…} @Override public void onError() {…} }); } }); }

@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); picasso.cancelRequest(merchantImage); } }

Page 144: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 145: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 146: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 147: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
Page 148: Nuking nasty memory leaks - GOTO Conference · dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

Py ⚔ twitter.com/Piwai