Note that there are some explanatory texts on larger screens.

plurals
  1. POListview in Fragment is causing Memory Leak
    primarykey
    data
    text
    <p>I have a FragmentActivity with a <code>FragmentMediaOverview</code> containing a list of <code>MediaItemView</code>s (each with a imageview and some text) and a click on one of the items opening a detail-Fragment. Now when I go back (via back button) and forth (click on listitem) several times from list to detail fragment I eventually run into OOM-Errors. I use <code>SoftReference</code>s for the bitmaps in the listitems as well as in the detail fragment. According to MAT there is an incresing number of <code>MediaItemView</code>s as well as <code>FragmentMediaOverview</code> instances, but I just cannot figure out why.</p> <p>I read this <a href="https://stackoverflow.com/questions/7083441/android-alertdialog-causes-a-memory-leak/">Android: AlertDialog causes a memory leak</a> , but couldn't solve it <code>null</code>ing out listeners.</p> <p>Here is my code:</p> <p>FragmentMediaOverview.java</p> <p>(This is not a ListFragment because for a tablet-layout the <code>MediaAdapter</code> needs to connect to a gridview)</p> <pre><code>public class FragmentMediaOverview extends Fragment { private static String TAG = FragmentMediaOverview.class.getSimpleName(); private MediaAdapter adapter; private OnMediaSelectedListener selListener; private ArrayList&lt;BOObject&gt; mediaItems; private ViewGroup layoutContainer; private AdapterView itemContainer; // list or gridview @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView"); layoutContainer = (ViewGroup) inflater.inflate(R.layout.fragment_media_overview, null); return layoutContainer; } @Override public void onAttach(Activity activity) { super.onAttach(activity); selListener = (OnMediaSelectedListener) activity; } @Override public void onDestroy() { super.onDestroy(); itemContainer.setOnItemClickListener(null); selListener = null; adapter = null; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); initUi(layoutContainer); displayMedia(); } private void initUi(ViewGroup layoutContainer) { itemContainer = (AdapterView) layoutContainer.findViewById(android.R.id.list); itemContainer.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position, long id) { BOMedia mediaItem = ((BOMedia) mediaItems.get(position)); //the FragmentActivity is coordinating the FragmentTransactions selListener.onMediaSelected(mediaItem); } }); } private void displayMedia() { Log.d(TAG, "Displaying List"); if (mediaItems == null) { loadMedia(); return; } Log.d(TAG, "List: " + mediaItems.size() + ", adapter: " + itemContainer.getAdapter()); if (adapter == null) { Log.d(TAG, "Create Adapter with " + mediaItems.size()); adapter = new MediaAdapter(getActivity(), mediaItems); } if (itemContainer.getAdapter() == null) { itemContainer.setAdapter(adapter); } else { adapter.setItems(mediaItems); adapter.notifyDataSetChanged(); } } private void loadMedia() { FragmentHelper.showProgressSpinner(layoutContainer, android.R.id.list); DbHelper.getInstance().getMedia(mediaType, new DbQueryFinishListener() { @Override public void onDbCallFinish(ArrayList&lt;BOObject&gt; objects) { if (!getActivity().isFinishing()) { mediaItems = objects; Collections.sort(mediaItems, new Comparator&lt;BOObject&gt;() { final Collator c = Collator.getInstance(Locale.GERMAN); @Override public int compare(BOObject s1, BOObject s2) { if (s2 != null &amp;&amp; ((BOMedia) s2).getTitle() != null &amp;&amp; s1 != null &amp;&amp; ((BOMedia) s1).getTitle() != null) { return c.compare(((BOMedia) s1).getTitle(),((BOMedia) s2).getTitle()); } else { return 0; } } }); displayMedia(); FragmentHelper.hideProgressSpinner(layoutContainer, android.R.id.list); } } @Override public void onDbCallException(Exception exception) { if (!getActivity().isFinishing()) { FragmentHelper.hideProgressSpinner(layoutContainer, android.R.id.list); } } }); } } </code></pre> <p>MediaAdapter.java</p> <pre><code>public class MediaAdapter extends BaseAdapter { private static final String TAG = MediaAdapter.class.getSimpleName(); private Context context; private ArrayList&lt;BOObject&gt; mediaItems; public MediaAdapter(Context c, ArrayList&lt;BOObject&gt; mediaItems) { super(); context = c; this.mediaItems = mediaItems; } @Override public int getCount() { return mediaItems.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = new MediaItemView(context); } ((MediaItemView)convertView).initialize((BOMedia) mediaItems.get(position)); return convertView; } public void setItems(ArrayList&lt;BOObject&gt; mediaItems) { this.mediaItems = mediaItems; } } </code></pre> <p>MediaItemView.java</p> <pre><code>public class MediaItemView extends LinearLayout { private static final String TAG = MediaItemView.class.getSimpleName(); private BOMedia item; private SoftReference&lt;Bitmap&gt; bm; private ImageView iv; private Context ctx; public MediaItemView(Context context) { super(context); LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(R.layout.view_media_item, this); this.ctx = context; } /** Init the view with a new BOMedia object * @param mediaItem */ public void initialize(BOMedia mediaItem) { this.item = mediaItem; initUI(); } private void initUI() { TextView title = (TextView) findViewById(R.id.itemText); iv = (ImageView) findViewById(R.id.itemImage); title.setText(Html.fromHtml(item.getTitle())); iv.setImageBitmap(null); bm = null; System.gc(); iv.invalidate(); if (item.getFilepathThumb() != null &amp;&amp; !item.getFilepathThumb().equals("")) { ExpansionPackManager.getInstance().getBitmapResource(item.getFilepathThumb(), false, new BitmapReadListener() { @Override public void onFileRead(BitmapResponseMessage message) { Log.d(TAG, "Bitmap read: " + message.getFilepath()); Bitmap image = message.getBitmap(); if (image != null &amp;&amp; message.getFilepath().equals(item.getFilepathThumb())) { bm = new SoftReference&lt;Bitmap&gt;(image); iv.setImageBitmap(bm.get()); Log.d(TAG, "image set"); } else { Log.d(TAG, "image too late: " + image); } } @Override public void onFileException(Throwable exception) { Log.d(TAG, "image exception"); } }); } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload