Skip to content
This repository has been archived by the owner. It is now read-only.

Memory leak in ViewPager #241

Open
fedotovsi opened this issue May 20, 2016 · 6 comments
Open

Memory leak in ViewPager #241

fedotovsi opened this issue May 20, 2016 · 6 comments

Comments

@fedotovsi
Copy link

I noticed memory leak in my project when I was using MvxFragmentStatePagerAdapter2.
I tried all viewPager adapters and
all of them have same problem,
it seems MvxFragmentsPresenter doesn't recycle internal fragment views.

Steps to reproduce

1.Put some large byte array in PagerAdapter as private field

2.Start application, it can be your example

3.Navigate to ViewPager or ViewPagerState

4.Navigate to another fragment, e.g. Home

5.Repeat steps 3 and 4 several times

6.See in profile how will grow up memory allocation.

Expected behavior

ViewPager and ViewPagerAdapter to be destroyed with fragment view

Actual behavior

Someone has ref to ViewPager, so memory is grow up after each createView-destryoView cycle

Configuration

Version: 4.1.4

@thefex
Copy link
Contributor

thefex commented May 20, 2016

I don't think it's MvvmCross bug - I think this is Android bug. I have developed one application which used a lot of pages in ViewPager before MvvmCross support library came in. I've used standard Android view pager adapters and implemented Mvvm support by my own. I had same problems as you have described - unfortunately I was not able to fix that (redesigned a bit UI to avoid ImageViews in pager fragments). My ImageViews bitmaps weren't disposed correctly thus sometimes when I had a lot of pages with ImageViews my application crashed with OutOfMemoryException.

@kjeremy
Copy link
Contributor

kjeremy commented May 20, 2016

This is most likely the issue here: https://stackoverflow.com/questions/18977923/viewpager-with-nested-fragments.

Here's a workaround I used in a previous project:

using System;
using Android.App;
using Java.Lang;
using Java.Lang.Reflect;

namespace MinefieldManagement.Droid.Helpers
{
    /// <summary>
    /// Cleans up the Fragment's child fragment manager.
    /// It should be used on any fragment that uses ChildFragmentManager.
    /// </summary>
    public static class ChildFragmentCleanupHelper
    {
        public static void OnDetach(Fragment fragment)
        {
            // Fix nested fragment's being put into an invalid state.
            // See: https://stackoverflow.com/questions/18977923/viewpager-with-nested-fragments
            // See: https://stackoverflow.com/questions/15207305/getting-the-error-java-lang-illegalstateexception-activity-has-been-destroyed/15656428#15656428
            // See: https://code.google.com/p/android/issues/detail?id=42601
            try
            {
                Class fragmentClass = Class.FromType(typeof(Fragment));
                Field childFragmentManager = fragmentClass.GetDeclaredField("mChildFragmentManager");
                childFragmentManager.Accessible = true;
                childFragmentManager.Set(fragment, null);
            }
            catch (NoSuchFieldException e)
            {
                throw new InvalidOperationException(e.Message);
            }
            catch (IllegalAccessException e)
            {
                throw new InvalidOperationException(e.Message);
            }
        }
    }
}

Then in your fragment:

public override void OnDetach()
{
    base.OnDetach();

    ChildFragmentCleanupHelper.OnDetach(this);
}

@thefex
Copy link
Contributor

thefex commented May 24, 2016

@kjeremy that won't help with memory leaks as I have used that "trick" (it has just solved crashes for me)

@kjeremy
Copy link
Contributor

kjeremy commented May 24, 2016

@thefex Xamarin profiler?

@fedotovsi
Copy link
Author

yes, I used Xamarin profiler.
Thanks for your answers it seems the problem in Xamarin or Android, because fragment is destroying normally, the problem is in controls which are in there, I supposed during fragment destroying it will enter in Control.Dispose() and I tried it without MvxFragment and it works the same. So I clear my resources in OnDestroyView manually and it seems the best solution for now.
I think issue can be closed, thanks for your support

@kjeremy
Copy link
Contributor

kjeremy commented May 31, 2016

@fedotovsi can you post your OnDestroyView code? I'm curious as to what you need to clear to make the leak go away. It may provide a clue. Did the profiler tell you what was kept alive?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

3 participants