Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the common memory leak application scenarios of Android

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is to share with you about the common memory leak application scenarios of Android. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

1. What are the common memory leak application scenarios? 1. Improper use of a single case

Singletons are one of the most common and frequently used design patterns in our development, so improper use can lead to memory leaks. Because the static nature of the singleton makes its life cycle as long as the application life cycle, if an object is no longer useful, but the singleton still holds its reference, then the object cannot be normally recycled throughout the life cycle of the application, resulting in a memory leak.

Such as:

Public class App {private static App sInstance; private Context mContext; private App (Context context) {this.mContext = context;} public static App getInstance (Context context) {if (sInstance = = null) {sInstance = new App (context);} return sInstance;}}

If the context passed in when calling the getInstance (Context context) method is the current active Activity or the Service of the current service and the context of the current fragment, when they are destroyed, the static singleton sIntance will also hold their references, resulting in objects such as the current activity, services, fragment, and so on cannot be recycled and released, resulting in memory leaks. The improper use of this context often leads to memory leaks, which requires us to pay more attention to the coding specifications.

2. Memory leak caused by static variables

The static variable is stored in the method area, and its life cycle starts from class loading to the end of the entire process. Once a static variable is initialized, the references it holds will not be released until the end of the process.

The code is as follows:

Public class MainActivity extends AppCompatActivity {private static Info sInfo; @ Override protected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); if (sInfo! = null) {sInfo = new Info (this);}} class Info {public Info (Activity activity) {}}

Info is a static member of Activity and holds a reference to Activity, but sInfo as a static variable must have a longer life cycle than Activity. So when Activity exits, sInfo still references that Activity,Activity cannot be recycled, which leads to a memory leak. In Android development, static holding may lead to memory leaks because of the inconsistent life cycle of its use, so we need to consider more about the reference relationship between members when creating statically held variables, and use statically held variables as little as possible to avoid memory leaks. Of course, we can also reset the static quantity to null at an appropriate time so that it no longer holds a reference, which can also avoid memory leaks.

3. Memory leak caused by non-static inner class

Non-static inner classes (including anonymous inner classes) hold references to external classes by default, which leads to memory leaks when the life cycle of non-static inner class objects is longer than that of external class objects. This kind of memory leak is very typical of the use of Handler, so we should be very familiar with it, we all know how to deal with this kind of memory leak.

Examples of the use of Handler:

Private void start () {Message msg = Message.obtain (); msg.what = 1; mHandler.sendMessage (msg);} private Handler mHandler = new Handler () {@ Override public void handleMessage (Message msg) {if (msg.what = = 1) {/ / ui Update}

In the Handler message mechanism, mHandler is saved as a member variable in the sent message msg, that is, msg holds the reference to mHandler, while mHandler is a non-static inner class instance of Activity, that is, mHandler holds the reference to Activity, so we can understand that msg indirectly holds the reference to Activity. The msg is sent to the message queue MessageQueue and then waits for polling by Looper (both MessageQueue and Looper are associated with threads, MessageQueue is a member variable referenced by Looper, and Looper is stored in ThreadLocal). Then when the Activity exits, the msg may still exist in the message column MessageQueue that is not processed or is being processed, which will cause the Activity to not be reclaimed, resulting in a memory leak for Activity.

How to avoid:

1. Adopt the method of static inner class + weak reference

Private static class MyHandler extends Handler {private WeakReference activityWeakReference; public MyHandler (MainActivity activity) {activityWeakReference = new WeakReference (activity); @ Override public void handleMessage (Message msg) {MainActivity activity = activityWeakReference.get () If (activity! = null) {if (msg.what = = 1) {/ / do the corresponding logic}}

MHandler holds Activity through weak references, and when GC performs garbage collection, it will reclaim and release the occupied memory units when it encounters Activity. So that memory leaks do not occur. However, it is still possible for msg to exist in message queuing MessageQueue.

2. When Activity is terminated, the callback of mHandler and the messages sent will be removed.

@ Override protected void onDestroy () {super.onDestroy (); mHandler.removeCallbacksAndMessages (null);}

Another situation where non-static inner classes cause memory leaks is to use Thread or AsyncTask asynchronous calls:

For example:

Thread:

Public class MainActivity extends AppCompatActivity {@ Override protected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); new Thread (new Runnable () {@ Override public void run () {try {Thread.sleep (2000) } catch (InterruptedException e) {e.printStackTrace ();}) .start ();}

AsyncTask:

Public class MainActivity extends AppCompatActivity {@ Override protected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); new AsyncTask () {@ Override protected Void doInBackground (Void...) Params) {/ / UI thread processes try {Thread.sleep (2000);} catch (InterruptedException e) {e.printStackTrace ();} return null;}} .execute ();}}

The above newly created child threads Thread and AsyncTask are anonymous inner class objects that implicitly hold references to external Activity by default, resulting in Activity memory leakage. To avoid memory leaks, you still need to use static inner classes + weak references as in Handler above (for example, static inner classes + weak references in Hanlder above).

4. Memory leak caused by non-registration or callback

For example, if we register a broadcast in Activity and do not cancel the registration after the Activity is destroyed, the new broadcast will always exist in the system and hold an Activity reference like the non-static inner class mentioned above, resulting in memory leakage. Therefore, after registering for the broadcast, you must cancel the registration after the Activity is destroyed.

This.unregisterReceiver (mReceiver)

When registering the observation mode, it will also cause a memory leak if it is not cancelled in time. For example, the viewer callback that registers a network request using Retrofit+RxJava also holds an external reference as an anonymous inner class, so you need to remember to unregister when it is not used or destroyed.

5. Timer Timer and TimerTask cause memory leak

When we destroy Activity, it is possible that Timer is still waiting for the execution of TimerTask, and its reference to Activity cannot be recycled, so when we destroy Activity, we have to cancel Timer and TimerTask immediately to avoid memory leaks.

6. Memory leak caused by the failure to clean up the objects in the collection

It's easy to understand that if an object is put into a collection such as ArrayList, HashMap, and so on, the collection will hold a reference to that object. When we no longer need this object, we do not remove it from the collection, so as long as the collection is still in use (and the object is useless), the object causes a memory leak. And if the collection is statically referenced, the useless objects in the collection will cause memory leaks. So when using the collection, it is necessary to remove the unused objects from the collection, or clear the collection, in order to avoid memory leaks.

7. Memory leak caused by unclosed or released resources

Turn it off when using IO, File streams, or resources such as Sqlite, Cursor, etc. These resources usually use buffering when reading and writing, and if they are not closed in time, these buffered objects will always be occupied and will not be released, resulting in a memory leak. So we turn them off when we don't need them, so that buffers can be released in time to avoid memory leaks.

8. Memory leak caused by animation

Animation is also a time-consuming task, for example, property animation (ObjectAnimator) is started in Activity, but when it is destroyed, the cancle method is not called. Although we can not see the animation, the animation will continue to play. The animation references the control and the control references Activity, which causes the Activity not to be released normally. Therefore, it is also necessary to cancel the attribute animation when Activity is destroyed to avoid memory leaks.

@ Override protected void onDestroy () {super.onDestroy (); mAnimator.cancel ();} 9, WebView causes memory leak

With regard to the memory leak of WebView, because WebView takes up memory for a long time after loading a web page and cannot be freed, we have to call its destory () method after Activity is destroyed to free memory.

In addition, when consulting the information related to the WebView memory leak, we can see this situation: the Callback under the Webview holds an Activity reference, so the Webview memory cannot be freed, even if methods such as Webview.destory () are called (after Android5.1).

The ultimate solution is to remove the WebView from the parent container before destroying the WebView, and then destroy the WebView.

@ Override protected void onDestroy () {super.onDestroy (); / / first remove WebView mWebViewContainer.removeView (mWebView); mWebView.stopLoading (); mWebView.getSettings (). SetJavaScriptEnabled (false) from the parent control; mWebView.clearHistory (); mWebView.removeAllViews (); mWebView.destroy ();} Thank you for reading! This is the end of this article on "what are the common memory leak application scenarios of Android?". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report