Preface
1. Introduction to Android memory leak1. What is a memory leak?
2. The harm of memory leak
3. Causes of memory leaks ① If the memory space is not recycled after use, it will cause memory leaks. Although Java has a garbage collection mechanism, there are still many code logics in Java that cause memory leaks. The garbage collector will recycle most of the memory space, but some memory space still retains references, but logically no longer used objects. At this time, the garbage collector is powerless and cannot recycle them, such as:
②Memory leaks on the Android (Java) platform refer to the fact that useless object resources maintain a reachable path with GC Roots, which makes the system unable to recycle; ③Then the objects popped from the stack will not be treated as garbage collection. Even if the program no longer uses these objects in the stack, they will not be recycled because the stack still holds references to these objects, commonly known as expired references. This memory leak is very hidden. 2. Detection of memory leak detection tools①Memory Monitor Located in Android Monitor, this tool can:
②Allocation Tracker This tool is used to:
③Heap Viewer This tool is used to:
④LeakCanary
Use it directly in the Application, then run the APP and it will automatically detect it. If it is detected, it will notify you on another APP and display the details.
3. Detailed explanation of common memory leak scenarios1. Singleton causes memory leak The singleton pattern is often used in Android development, but if used improperly, it can lead to memory leaks. Because the static nature of the singleton makes its life cycle as long as the life cycle of the application, if an object is no longer useful, but the singleton still holds its reference, it cannot be properly recycled during the entire life cycle of the application, resulting in memory leaks.
For singletons like the one in the code above, if we pass in a context parameter such as Activity or Service when calling the getInstance(Context context) method, memory leaks will occur. Take Activity as an example. When we start an Activity and call the getInstance(Context context) method to get the AppSettings singleton, passing in Activity.this as context, the AppSettings singleton sInstance holds a reference to the Activity. When we exit the Activity, the Activity is useless. However, because sIntance is a static singleton (which exists throughout the life cycle of the application), it will continue to hold a reference to the Activity, causing the Activity object to be unable to be recycled and released, which causes a memory leak. To avoid memory leaks caused by such singletons, we can change the context parameter to a global context:
2. Static variables cause memory leaks Static variables are stored in the method area, and their life cycle starts from class loading and ends at the end of the entire process. Once a static variable is initialized, the reference it holds will not be released until the process ends. For example, in the following situation, in order to avoid repeated creation of info in Activity, sInfo is used as a static variable:
Info is a static member of Activity and holds a reference to Activity, but sInfo is a static variable and its life cycle is definitely longer than Activity. So when Activity exits, sInfo still references Activity and Activity cannot be recycled, which leads to memory leaks. In Android development, static holding may often cause memory leaks due to inconsistent life cycles, so when creating new static holding variables, we need to consider the reference relationship between members and use static holding variables as little as possible to avoid memory leaks. Of course, we can also reset the static variable to null at an appropriate time so that it no longer holds a reference, which can also avoid memory leaks. 3. Non-static inner classes cause memory leaks Non-static inner classes (including anonymous inner classes) hold references to outer classes by default. When the lifecycle of a non-static inner class object is longer than that of an outer class object, memory leaks will occur. A typical scenario for memory leaks caused by non-static inner classes in Android development is the use of Handlers. Many developers write Handlers like this:
Some people may say that mHandler does not hold the reference of Activity as a static variable, and its life cycle may not be longer than that of Activity, so it should not necessarily cause memory leaks. Obviously, this is not the case! Those who are familiar with the Handler message mechanism know that mHandler will be saved as a member variable in the sent message msg, that is, msg holds the reference of mHandler, and mHandler is a non-static inner class instance of Activity, that is, mHandler holds the reference of Activity, so we can understand that msg indirectly holds the reference of Activity. After msg is sent, it is first placed in the message queue MessageQueue, and then waits for Looper's polling processing (MessageQueue and Looper are both associated with threads, MessageQueue is a member variable referenced by Looper, and Looper is stored in ThreadLocal). Then when the Activity exits, msg may still exist in the message queue MessageQueue and is not processed or being processed, which will cause the Activity to be unable to be recycled, resulting in a memory leak in the Activity. Usually in Android development, if you want to use inner classes but want to avoid memory leaks, you usually use static inner classes + weak references.
mHandler holds the Activity through weak references. When GC performs garbage collection, it will recycle and release the memory unit occupied by the Activity. In this way, memory leaks will not occur. The above approach does avoid memory leaks caused by the Activity. The sent msg no longer holds the reference to the Activity, but the msg may still exist in the message queue MessageQueue, so it is better to remove the callback of mHandler and the sent message when the Activity is destroyed.
Another situation where non-static inner classes cause memory leaks is when using Thread or AsyncTask. To avoid memory leaks, you still need to use static inner classes + weak applications like the Handler above (the code is not listed, refer to the correct writing method of Handler above). 4. Failure to cancel registration or callback causes memory leak For example, if we register a broadcast in an Activity and do not cancel the registration after the Activity is destroyed, the broadcast will always exist in the system, holding an Activity reference like the non-static inner class mentioned above, causing a memory leak. Therefore, after registering a broadcast, you must cancel the registration after the Activity is destroyed. When registering an observer mode, memory leaks can also occur if the registration is not canceled in time. For example, when using Retrofit+RxJava to register an observer callback for a network request, it also holds an external reference as an anonymous inner class, so you need to remember to cancel the registration when it is not used or destroyed. 5. Timer and TimerTask cause memory leaks Timer and TimerTask are usually used in Android to perform some timing or cyclic tasks, such as implementing an infinitely rotating ViewPager:
When our Activity is destroyed, it is possible that the Timer is still waiting to execute the TimerTask. The reference it holds to the Activity cannot be recycled. Therefore, when our Activity is destroyed, we must immediately cancel the Timer and TimerTask to avoid memory leaks. 6. Objects in the collection are not cleaned up, causing memory leaks This is easy to understand. If an object is put into a collection such as ArrayList or HashMap, the collection will hold a reference to the object. When we no longer need the object, we do not remove it from the collection. As long as the collection is still in use (and the object is no longer useful), the object will cause a memory leak. And if the collection is referenced statically, the useless objects in the collection will cause a memory leak. Therefore, when using a collection, you should remove unused objects from the collection in a timely manner, or clear the collection, to avoid memory leaks. 7. Memory leaks caused by resources not being closed or released When using IO, File stream, Sqlite, Cursor and other resources, they should be closed in time. These resources usually use buffers when performing read and write operations. If they are not closed in time, these buffer objects will be occupied and not released, resulting in memory leaks. Therefore, we should close them in time when they are not needed so that the buffers can be released in time to avoid memory leaks. 8. Property animation causes memory leaks Animation is also a time-consuming task. For example, if you start an attribute animation (ObjectAnimator) in an Activity, but do not call the cancel method when destroying it, we will not see the animation, but the animation will continue to play. The animation references the control, and the control references the Activity, which will cause the Activity to fail to be released normally. Therefore, you should also cancel the attribute animation when destroying the Activity to avoid memory leaks. 9. WebView causes memory leak Regarding the memory leak of WebView, since WebView will occupy memory for a long time after loading a web page and cannot be released, we need to call its destory() method to destroy it and release memory after the Activity is destroyed. In addition, when looking up the relevant information about WebView memory leak, I saw this situation: the Callback under Webview holds the Activity reference, causing the Webview memory to be unable to be released, and even calling methods such as Webview.destory() cannot solve the problem (after Android 5.1). The final solution is: before destroying WebView, you need to remove WebView from the parent container first, and then destroy WebView. Summarize
When something is added to a collection, there should be a corresponding deletion. Cancel attribute animation in time, pay attention to webview memory leak problem |
<<: Google Chrome for Android gets two-factor authentication
>>: How to choose a mobile phone? I'll share my experience of changing phones over the years.
With the arrival of autumn, the demand for mutton...
Is it time? Is it fate? Often, the development of...
Translator's note: The International Departme...
Review expert: Wang Lei, National Park and Nature...
Many customers often ask what the SEO work conten...
Since the CES (Consumer Electronics Show) at the ...
Two years ago, when people talked about drinking ...
The demand for second-hand goods market is growin...
The price of a video of African children holding ...
Produced by: Science Popularization China Author:...
On the evening of September 23, China Evergrande ...
If you were asked what is the largest land animal...
What is a Douyin account? A Douyin account that i...