Activityを切り替えずに、動的にListViewを作ったり消したりしていると、ガベージコレクションを何度実行しても回収されず、何故かメモリリークっぽい事になります。

以下再現ソースです。

package com.test;

import android.app.Activity;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class Test000Activity extends Activity {

	private LinearLayout layout;
	private int count = 0;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        layout = new LinearLayout(this);
        setContentView(layout);
        next();
    }
    
    private class Next implements Runnable {

		public void run() {
			layout.removeAllViews();
			
			count++;
			if (count == 10) {
				Log.d("test", "おわり");
				return;
			}
			else {
				Log.d("test", "next:" + count);
			}
			
			MyListView listView = new MyListView(Test000Activity.this);
			listView.setAdapter(new MyListAdapter());
			layout.addView(listView);
			next();
		}    	
    }
    
    private void next() {
    	new Handler().postDelayed(new Next(), 500);
    }
    
    private static class MyListView extends ListView {
		public MyListView(Context context) {
			super(context);
		}
    }
    
    private static class MyListAdapter implements ListAdapter {
		public int getCount() {
			return 50;
		}
		public Object getItem(int arg0) {
			return null;
		}
		public long getItemId(int position) {
			return 0;
		}
		public int getItemViewType(int position) {
			return 0;
		}
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView != null) {
				return convertView;
			}
			TextView tv = new TextView(parent.getContext());
			tv.setText("test");
			tv.setMinimumHeight(40);
			return tv;
		}
		public int getViewTypeCount() {
			return 1;
		}
		public boolean hasStableIds() {
			return false;
		}
		public boolean isEmpty() {
			return false;
		}
		public void registerDataSetObserver(DataSetObserver observer) {
		}
		public void unregisterDataSetObserver(DataSetObserver observer) {
		}
		public boolean areAllItemsEnabled() {
			return true;
		}
		public boolean isEnabled(int position) {
			return true;
		}
	}
}

これを実行すると、500msおきにMyListViewを作ったり消したりします。
10回繰り返すと終わります。

このあとで、DDMSのガベコレボタンを連打してDump HPROF fileしてみたのがこちら。
leak
残っちゃっています。

ただ、デバッグ実行ではなく、通常の実行だとこのリークは検出されないので、実害は無いのですが、なんだか気持ち悪いのでなんとかしたいところです。
この辺ご存知の方はこっそり教えてもらえると助かります!

記事検索

アーカイブ