View + Tag = memory leak?

At the heart of:

  • Activity - recreates (onCreate-onDestroy) with every change of orientation.
  • The view consists of a ViewFlipper with two children: a simple RelativeLayout and a ListView
  • ListView strings have complex layout and related tags

The problem is that I have a memory leak with every orientation change - the activity remains in memory with the whole layout of the view. The activity itself is a context, so it will remain in memory until related objects are connected. So now I am trying to find out why leaks occur.

View has a setTag () method. I use it to store some string information (so each row (View) in the ListView has associated tags).

But how do views and GCs work with tags? My tag objects (holders) contain links to the views, but if view removes the link to it, then these links (with the tag itself) will be easily assembled.

Has anyone encountered similar issues with ListViews?

PS I wonder how GC clears layouts - tons of circular links, contexts, holders, etc.

+4
source share
4 answers

Its easy to leak links to activity when changing orientation. There are several blog posts about this - it seems to me that I am reading:

http://ttlnews.blogspot.com/2010/01/attacking-memory-problems-on-android.html

http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html

http://code.google.com/p/android/issues/detail?id=2391

In a nutshell, in your onRetainNonConfigurationInstance method onRetainNonConfigurationInstance you just want to be careful that you remove any references to View objects and, in turn, links to actions, progress bars, etc.

The good template that I use has an internal StateHolder class that contains a reference to Activity, but I implement the setActivityForTasks method, which I just pass NULL, which in turn sets all the links to activity to NULL. Then, when you return through your activity after changing orientation, you can simply call setActivityForTasks(this) to reset the current activity.

The only conclusion is that it is simply NULL from any references to anything. onRetainNonConfigurationInstance Related onRetainNonConfigurationInstance

+3
source

First, you can leak objects if you use the View.setTag(int, Object) method. Tags set using this method are stored in a static WeakHashMap with the View key. Therefore, if you store references to the child view in the tags of the parent view, all these views and the context that they created (parent activity) will leak. This is because each child view contains a reference to the parent, so the parent view will never be compiled by GC.

There is a simple way to model this behavior:

 public static class MainActivity extends ListActivity { private final WeakHashMap<Parent, Parent.Child> mMap = new WeakHashMap<Parent, Parent.Child>(); @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // If parents were collected OOM error wouldn't be thrown. // But they aren't collected so we get OOM here. for (int i = 0; i < 10; ++i) { Parent parent = new Parent(); mMap.put( parent, parent.mChild ); } } } public static class Parent { public final Child mChild = new Child(); public class Child { private final byte[] mJunk = new byte[10*1024*1024]; } } 

Secondly, it seems that the ListView class is causing a memory leak. This means that the list, all of its recycled children and its parenting activity are leaking. Here is some information about this error:

+9
source

I think you might have some non-static inner classes that always keep a pointer to an instance of the surrounding object. For instance:

 public class A { private class B { // ... } // b stores a reference to the instance of A private B b = new B(); } 

If you use the setTag () method (for example, for the ViewHolder class), never store any references to parent objects. In fact, you should declare this class static.

In addition, to avoid memory leaks, you should always pass the result of getApplicationContext () to methods that need context and not reference the process itself.

+4
source

Gingerbread and lower versions of Android View.setTag (int key, Object tag) memory leak. Do not use it. It has been fixed in ICS.

+2
source

Source: https://habr.com/ru/post/1344987/


All Articles