As an experiment, I tried removing the GListView from it's parent
LinearLayout when I no longer needed it.  When I did this, the garbage
collector was then able to recycle the parent (the LinearLayout), but
the GListView remained in memory and was not freed.

Using the Memory Analyzer, I can list the incoming references for one
of the GListViews which should be freed but is not:

Class
Name                                                              |
Shallow Heap | Retained Heap
-------------------------------------------------------------------------------------------------------
com.gabysoft.system.GListView @ 0x43e6fec8
Unknown                      |          672 |         3,432
|- host android.view.View$ScrollabilityCache @
0x43e701b8               |           80 |           584
|- this$0 android.widget.AbsListView$RecycleBin @
0x43e70488            |           40 |            96
|- mCallback android.graphics.drawable.StateListDrawable @
0x43e70500   |           64 |         1,464
|- this$0 android.widget.AdapterView$AdapterDataSetObserver @
0x43e70d10|           16 |            16
'- Total: 4
entries
|              |
-------------------------------------------------------------------------------------------------------

Does this give anyone a clue as to where the problem might be?  Surly
I must be doing something wrong here. There cannot be this kind of
leak in general can there?

Thanks.


On Oct 21, 5:47 pm, John Gaby <jg...@gabysoft.com> wrote:
> I have already tried making the ListAdapter a completely separate
> public class, and it does not seem to help.  I can post that code, if
> it would be helpful (perhaps I have something wrong with it).
>
> Thanks.
>
> On Oct 21, 5:33 pm, Mark Murphy <mmur...@commonsware.com> wrote:
>
> > Move your ListAdapter to a public class or a static inner class of
> > your Activity, and see if that helps. A ListView being its own adapter
> > is not a well-trod path.
>
> > On Thu, Oct 21, 2010 at 8:04 PM, John Gaby <jg...@gabysoft.com> wrote:
> > > I am still struggling with a memory leak associated with a ListView.
> > > I have created the following small program which exhibits this
> > > behavior.
>
> > > What I do is create 2 LinearLayouts.  The first has a Button and a
> > > GListView control.  The code for GListView is below, but it just sub-
> > > classes ListView, and implements the ListAdapter interface.  When the
> > > GListView is created, it sets it's adapter to itself.
>
> > > Now when you press the button I switch to the second LinearLayout.
> > > This layout has only a single button.  When you press this button, I
> > > create a new 1st layout with a new GListView and set it as the active
> > > view.
>
> > > Run the program, and switch between the two views 20 times.  Then
> > > bring up the DDMS and force a garbage collection.  Then Dump the heap,
> > > and use the Memory Analyzer and you will find 21 GListView objects
> > > remaining.  That is, the 20 GListViews that are not longer connected
> > > to anything have NOT been freed.
>
> > > Now if I comment out the 'setAdapter(this)' function in the GListView
> > > constructor and repeat the above, I find that there is only 1
> > > GListView that remains.  That is, in this case, all of the unused
> > > GListViews have been properly recycled.
>
> > > Someone suggested that I create a private class within my GListView to
> > > handle the ListAdapter interface, and I tried that, but it did not
> > > help.
>
> > > Surely there is some way to make these objects go away when they are
> > > no longer used anywhere.  (Isn't that what garbage collection is all
> > > about?)
>
> > > Any help would be appreciated.  I am really pulling my hair out on
> > > this one.
>
> > > Thanks.
>
> > > /*
> > >  * Activity
> > >  */
>
> > > package com.gabysoft.memoryleak;
>
> > > import android.app.Activity;
> > > import android.os.Bundle;
> > > import android.view.View;
> > > import android.widget.Button;
> > > import android.widget.LinearLayout;
> > > import android.widget.ListView;
>
> > > public class MemoryLeak extends Activity implements
> > > android.view.View.OnClickListener
> > > {
> > >    LinearLayout ll2;
> > >    boolean page2 = false;
>
> > >    private LinearLayout CreateLayout()
> > >    {
> > >        LinearLayout ll = new LinearLayout(this);
>
> > >        Button btn1 = new Button(this);
> > >        ListView    lv    = new GListView(this);
>
> > >        btn1.setText("Press");
> > >        btn1.setLayoutParams(new LinearLayout.LayoutParams(100, 40));
> > >        btn1.setOnClickListener(this);
>
> > >        ll.addView(btn1);
> > >        ll.addView(lv);
>
> > >        return(ll);
> > >    }
>
> > >    /** Called when the activity is first created. */
> > >   �...@override
> > >    public void onCreate(Bundle savedInstanceState)
> > >    {
> > >        super.onCreate(savedInstanceState);
>
> > >        CreateLayout();
>
> > >        LinearLayout ll = CreateLayout();
> > >        ll2 = new LinearLayout(this);
>
> > >        Button btn2 = new Button(this);
>
> > >        btn2.setText("Back");
> > >        btn2.setLayoutParams(new LinearLayout.LayoutParams(100, 40));
> > >        btn2.setOnClickListener(this);
>
> > >        ll2.addView(btn2);
>
> > >        setContentView(ll);
> > >    }
>
> > >   �...@override
> > >    public void onClick(View v)
> > >    {
> > >        if (page2)
> > >        {
> > >            LinearLayout ll = CreateLayout();
>
> > >            setContentView(ll);
>
> > >            page2 = false;
> > >        }
> > >        else
> > >        {
> > >            setContentView(ll2);
> > >            page2 = true;
> > >        }
> > >    }
>
> > > }
>
> > > /*
> > >  * GListView
> > >  */
> > > package com.gabysoft.memoryleak;
>
> > > import android.content.Context;
> > > import android.database.DataSetObserver;
> > > import android.view.View;
> > > import android.view.ViewGroup;
> > > import android.widget.AdapterView;
> > > import android.widget.ListAdapter;
> > > import android.widget.ListView;
> > > import android.widget.TextView;
>
> > > public class GListView extends ListView implements ListAdapter
> > > {
> > >    Context m_context;
> > >    DataSetObserver m_observer = null;
>
> > >    public GListView(Context context)
> > >    {
> > >        super(context);
>
> > >        m_context    = context;
>
> > >        setAdapter(this);
>
> > >        setChoiceMode(CHOICE_MODE_SINGLE);
> > >    }
>
> > >    /*
> > >     * ListAdapter
> > >     */
>
> > >   �...@override
> > >    public boolean areAllItemsEnabled()
> > >    {
> > >        return true;
> > >    }
>
> > >   �...@override
> > >    public boolean isEnabled(int position)
> > >    {
> > >        return true;
> > >    }
>
> > >   �...@override
> > >    public int getCount()
> > >    {
> > >        return(0);
> > >    }
>
> > >   �...@override
> > >    public Object getItem(int position)
> > >    {
> > >        return null;
> > >    }
>
> > >   �...@override
> > >    public long getItemId(int position)
> > >    {
> > >        return(position);
> > >    }
>
> > >   �...@override
> > >    public int getItemViewType(int position)
> > >    {
> > >        return 0;
> > >    }
>
> > >   �...@override
> > >    public View getView(int position, View convertView, ViewGroup
> > > parent)
> > >    {
> > >        TextView tv = new TextView(m_context);
>
> > >        tv.setText("Item");
>
> > >        return(tv);
> > >    }
>
> > >   �...@override
> > >    public int getViewTypeCount()
> > >    {
> > >        return 1;
> > >    }
>
> > >   �...@override
> > >    public boolean hasStableIds()
> > >    {
> > >        return false;
> > >    }
>
> > >   �...@override
> > >    public boolean isEmpty()
> > >    {
> > >        return false;
> > >    }
>
> > >   �...@override
> > >    public void registerDataSetObserver(DataSetObserver observer)
> > >    {
> > >        m_observer    = observer;
> > >    }
>
> > >   �...@override
> > >    public void unregisterDataSetObserver(DataSetObserver observer)
> > >    {
> > >        m_observer    = null;
> > >    }
> > > }
>
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Android Developers" group.
> > > To post to this group, send email to android-developers@googlegroups.com
> > > To unsubscribe from this group, send email to
> > > android-developers+unsubscr...@googlegroups.com
> > > For more options, visit this group at
> > >http://groups.google.com/group/android-developers?hl=en
>
> > --
> > Mark Murphy (a Commons 
> > Guy)http://commonsware.com|http://github.com/commonsguyhttp://commonsware.com/blog|http://twitter.com/commonsguy
>
> > Android App Developer Books:http://commonsware.com/books

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to