I have an activity which does this:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
ListView lv = (ListView) findViewById(R.id.ListList);
lv.setItemsCanFocus(true);
lv.setOnItemClickListener(this);
adapter = new ListAdapter(this, lv, model, R.layout.simple, this);
lv.setAdapter(adapter);
}
My list adapter class looks like this.
public static class ListAdapter extends ArrayAdapter<ListItem>
public ListAdapter(Activity activity, ListView lv, List<ListItem> model, int resource, OnActionClickListener onActionClickListener) {
super(activity, android.R.layout.simple_list_item_1, model);
....
}
If I do a orientation change, about 20 times, it will run out of memory and give me an error like this:
12-22 17:33:44.977: E/dalvikvm-heap(29145): 1536000-byte external allocation too large for this process.
If I don't setup the rest of the code in onCreate (past setContentView), I don't have an issue.
I'm guessing I'm holding on (inadvertantly) to an instance of the activity, but I'm not sure how.
Any ideas?
tia.
So the thing that is causing the problem is "lv.setAdapter(adapter);" -- if I comment out that line, I don't have the issue... I tried lv.setAdapter(null) in onDestroy() - didn't help. I also added this (http://stackoverflow.com/questions/1147172/what-android-tools-and-methods-work-best-to-find-memory-resource-leaks) to onDestroy() as well - nothing seems to help.
So, I've narrowed it down as small as I can go.
Here is the main TestAppActivity.java file.
package com.junk.test;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class TestAppActivity extends Activity {
protected ArrayList<ListItem> model = new ArrayList<ListItem>();
protected ListAdapter adapter = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView lv = (ListView) findViewById(R.id.ListList);
lv.setItemsCanFocus(true);
adapter = new ListAdapter(this, lv, model);
lv.setAdapter(adapter);
if (savedInstanceState == null) {
Log.i("test", "@@ start");
new Thread(new Runnable() {
@Override
public void run() {
try {
boolean change = true;
Thread.sleep(4 * 1000);
for (int ii = 0; ii < 200; ii++) {
setRequestedOrientation(change ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Thread.sleep(4 * 1000);
change = !change;
Log.i("test", "@@ change: " + (ii+1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
Log.i("test", "@@ complete!");
}
}
}).start();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// doesn't make any difference.
// ListView lv = (ListView) findViewById(R.id.ListList);
// lv.setAdapter(null);
// adapter.clear();
// adapter = null;
unbindDrawables(findViewById(R.id.ListList));
System.gc();
}
private void unbindDrawables(View view) {
if (view == null) { return; }
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
if (view instanceof AdapterView) {
} else {
((ViewGroup) view).removeAllViews();
}
}
}
public static class ListItem {
public int x;
}
public static class ListAdapter extends ArrayAdapter<ListItem> implements View.OnClickListener {
public ListAdapter(Activity activity, ListView lv, List<ListItem> model) {
super(activity.getApplicationContext(), android.R.layout.simple_list_item_1, model);
}
@Override
public void onClick(View v) {
}
}
}
And here is main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@drawable/player_background">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<ListView
android:id="@+id/ListList"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:choiceMode="singleChoice"
android:cacheColorHint="#00000000"
android:dividerHeight="3dp"
android:overScrollFooter="@null" />
</LinearLayout>
And it is STILL leaking - takes like 110 or so orientation changes, but eventually it gives an allocation error!
http://stackoverflow.com/questions/3910473/i-have-a-memory-leak-using-listactivity-in-android/6530551#6530551
http://stackoverflow.com/questions/3997993/memory-lead-when-using-listview-in-android – user645402 Jan 06 '12 at 17:33