28. Dalvik
07-01 15:56:16.785: I/dalvikvm-heap(30615): Grow heap (frag case) to 38.179MB for
8294416-byte allocation
07-01 15:56:17.625: I/Choreographer(30615): Skipped 35 frames! The application may be
doing too much work on its main thread.
07-01 15:56:19.035: D/dalvikvm(30615): GC_CONCURRENT freed 35838K, 43% free
51351K/89052K, paused 3ms+5ms, total 106ms
07-01 15:56:19.035: D/dalvikvm(30615): WAIT_FOR_CONCURRENT_GC blocked 96ms
29. GC Reason
GC_CONCURRENT - A concurrent GC that frees up memory as your heap begins to fill up.
GC_FOR_MALLOC - A GC caused because your app attempted to allocate memory when your
heap was already full, so the system had to stop your app and reclaim memory.
GC_HPROF_DUMP_HEAP - A GC that occurs when you request to create an HPROF file to
analyze your heap.
GC_EXPLICIT - An explicit GC, such as when you call gc() (which you should avoid
calling and instead trust the GC to run when needed).
GC_EXTERNAL_ALLOC - This happens only on API level 10 and lower (newer versions
allocate everything in the Dalvik heap). A GC for externally allocated memory (such
as the pixel data stored in native memory or NIO byte buffers).
30. ART
07-01 16:00:44.531: I/art(198): Explicit concurrent mark sweep GC freed 700(30KB)
AllocSpace objects, 0(0B) LOS objects, 792% free, 18MB/21MB, paused 186us total
12.763ms
07-01 16:00:46.517: I/art(29197): Background partial concurrent mark sweep GC freed
74626(3MB) AllocSpace objects, 39(4MB) LOS objects, 1496% free, 25MB/32MB, paused
4.422ms total 1.371747s
07-01 16:00:48.534: I/Choreographer(29197): Skipped 30 frames! The application may be
doing too much work on its main thread.
07-01 16:00:48.566: I/art(29197): Background sticky concurrent mark sweep GC freed
70319(3MB) AllocSpace objects, 59(5MB) LOS objects, 825% free, 49MB/56MB, paused
6.139ms total 52.868ms
31. GC Reason
Concurrent - A concurrent GC which does not suspend app threads. This GC runs in a
background thread and does not prevent allocations.
Alloc - The GC was initiated because your app attempted to allocate memory when your
heap was already full. In this case, the garbage collection occurred in the
allocating thread.
Explicit - The garbage collection was explicitly requested by an app, for instance,
by calling gc() or gc().
NativeAlloc - The collection was caused by native memory pressure from native
allocations such as Bitmaps or RenderScript allocation objects
55. How to?
public class GetTaxiDriverBoxApp extends Application {
protected RefWatcher mRefWatcher;
public void onCreate() {
super.onCreate();
mRefWatcher = installLeakCanary();
}
protected RefWatcher installLeakCanary() {
return RefWatcher.DISABLED;
}
}
56. In Debug Only
public class DebugApplication extends GetTaxiDriverBoxApp {
@Override
protected RefWatcher installLeakCanary() {
mRefWatcher = LeakCanary.install(this, LeakSlackUploadService.class,
AndroidExcludedRefs.createAppDefaults().build());
return mRefWatcher;
}
}
57. When should be killed - watched it
@Override
public void onDetach() {
super.onDetach();
GetTaxiDriverBoxApp.getRefWatcher(getContext()).watch(this);
}
67. private final View.OnClickListener mButtonHandler = new View.OnClickListener() {
@Override public void onClick(View v) {
final Message m;
if (v == mButtonPositive && mButtonPositiveMessage != null) {
m = Message.obtain(mButtonPositiveMessage);
}
//...some other code
if (m != null) {
m.sendToTarget();
}
// Post a message so we dismiss after the above handlers are executed.
mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface)
.sendToTarget();
}
69. Check the square blog
Wrapper for clickListener and clear it on detach
Or
Send idle messages to clean app the messages
https://corner.squareup.com/2015/08/a-small-leak.html
71. Do not keep long-lived references to a context-
activity
public static Context mContext;
public NoLifeCycleClass(Activity myActivity) {
mContext = (Context) myActivity;
}
72. Try using the context-application instead of a
context-activity
StringUtilsUI.doSomeLongRunningTask(getApplicationContext());
73. Avoid non-static inner classes
public class DialogCountdown extends BaseDialogFragment {
private class CountDownHandler extends Handler {
//do some work
}
}
74. Avoid non-static inner classes
private static class CountDownHandler extends Handler {
private final WeakReference<DialogCountdown> mDialogCountdownWeakReference;
public CountDownHandler(DialogCountdown dialogCountdown) {
super();
mDialogCountdownWeakReference = new WeakReference<>(dialogCountdown);
}
public void handleMessage(Message msg) {
if(mDialogCountdownWeakReference.get()!=null) {
mDialogCountdownWeakReference.get().onCountDown();
}
}
75. Clean/Stop all your handlers, animation listeners
onDestroy();
protected void onStop() {
super.onStop();
mHandler.clearAllMessages();
unregisterReceivers();
heatMapsDone();
if (mServiceBound) {
mServiceBound = false;
Services.unbindFromRidesService(this, this);
}
if (mMapStateMachine != null) {
mMapStateMachine.stop();
mMapStateMachine = null;
}
}