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

Reply via email to