In fact, this article is a continuation of this topic:
Memory analysis for Android applications . Anyone who wants to explore the issue in detail will be welcome under the cut.
So let's go ...
Analyzing the state of memory using the tools described in
this article is a very necessary and useful thing, but it is not always convenient and appropriate to do this.
It would be nice to be able to track memory leaks without any third-party tools so that even an inexperienced tester could find memory leaks without access to a computer.
How to do it
We will come to the aid of a feature class
WeakReference .
Below is an example of a class that will help track memory leaks. This class does not pretend to originality, and perhaps someone already even uses something similar in his project. The class, for obvious reasons, was simplified and slightly modified, but it performs its main function. Let me just say that for greater convenience, you can add at least the number of “leaked” objects to the resulting list.
package com.company.product; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Vector; import android.content.Context; import android.content.Intent; import android.text.TextUtils; public class LeaksManager { private static LeaksManager mThis = null; private final Vector<WeakReference<Object>> mRefs = new Vector<WeakReference<Object>>(); private LeaksManager() { super(); } public static LeaksManager getThis() { if (mThis == null) { mThis = new LeaksManager(); } return mThis; } public <T> T monitorObject(T obj) { if (obj == null) { return obj; } for (WeakReference<Object> ref : mRefs) { if (ref.get() == obj) { return obj; } } mRefs.add(new WeakReference<Object>(obj)); return obj; } public Vector<String> checkLeaks() { System.gc(); Vector<String> names = new Vector<String>(); for (int i = mRefs.size() - 1; i >= 0; i--) { WeakReference<Object> ref = mRefs.elementAt(i); Object obj = ref.get(); if (obj != null) { String className = obj.getClass().getSimpleName(); addUniqueClassName(names, TextUtils.isEmpty(className) ? "Unknown class name" : className); } else { mRefs.remove(i); } } mRefs.trimToSize(); return names; } private void addUniqueClassName(Vector<String> names, String className) { int index = -1; for (int j = 0; j < names.size(); j++) { if (names.elementAt(j).equals(className)) { index = j; break; } } if (index == -1) { names.add(names.getClass().getSimpleName()); } } }
')
How to use it
First you have to write a simple Activity, which will take and display the list of lines returned by the
LeaksManager.checkLeaks()
function. This Activity is very simple, so I do not see much point in citing its code.
Next, we add each object that needs to be monitored to the LeaksManager as follows:
Object obj = LeaksManager.getThis().monitorObject(new Object());
Further, in a convenient place for you, you place an Activity call with a list of memory leaks, and if the list is empty, then everything is fine, and if something remains in it even after several launches of this Activity itself, that is, you should think about it.
In general, this is all that needs to be done.
Comments
There is no point in tracking all created objects - most objects are context-sensitive, and therefore it is quite enough for them to call monitorObject () in onCreate () of each Activity, service, and perhaps in the stream designer.
This class in no way eliminates the need to use the tools described in
this article, but it is quite easy to control memory leaks to both developers and testers. On a project where I participate, before each non-trivial submission it is customary to do such a “quick” test for memory leaks - it takes little time and allows you to immediately detect problems, not allowing them to identify themselves before passing the release.
PS
I hope this article will be useful to someone.
If this article is interesting, then in the next article I will tell about the tricky features of the class
AsyncTask