#StackBounty: #android #memory-leaks #leakcanary How to prevent memory leaks when using dynamic screens?

Bounty: 50

I’m creating an app that has screens that present data to the user.
Each Screen has its own data and its own layout, so it has a method to return an int that represent the layout that is used to inflate it, then this View is passed to a function to find the specific views and populate it with data.

The lifecycle goes like this:
MainPresenter:

screen.getNextScreen ->
screen.getLayout -> 
view = inflateScreen ->
screen.populateScreen(view) ->
(wait for time elappsed or click) -> repeat

Those Screens are also needed in SettingsActivity to enabledisable them.

So i’ve created a singleton ScreenProvider, it initializes once and then returns the list.

public class ScreenProvider {

    private List<Screen> screens;

    private static ScreenProvider instance = new ScreenProvider();

    public static ScreenProvider getInstance(){
        return instance;
    }

    private ScreenProvider() {
        screens = new ArrayList<>();

        screens.add(new Welcome());
        screens.add(new CompoundScreen());
        screens.add(new Times());
        screens.add(new Messages());
        screens.add(new Weekly());
    }

    public List<Screen> getScreenList() {
        return Lists.newArrayList(screens);
    }
}

Its seam that when running to long the app crashes or get closed for memory leaks, so i’ve added leakcanary, and this an example for its report:

MainActivity has leaked:
D: * static ScreenProvider.!(instance)!
D: * ↳ ScreenProvider.!(screens)!
D: * ↳ ArrayList.!(array)!
D: * ↳ array Object[].!([0])!
D: * ↳ CompoundScreen.!(disposable)!
D: * ↳ LambdaObserver.!(onNext)!
D: * ↳ -$$Lambda$Screen$67KdQ1jl3VSjSvoRred5JqLGY5Q.!(f$1)!
D: * ↳ AppCompatTextView.mContext
D: * ↳ MainActivity

This is just a single example, but almost every screen has such leak.
The LeakCanary report shows that TextView has this: D: | mAttachInfo = null so i assume it is not the problem.
Also every Screen has an onHide() to clear disposables, that is called when current Screen hides and in MainActivity.onStop().

How to fix this leak?
Should i not use a singleton for the screens?
If not, how do i access the screen list from other activities?

** Editing **
Adding some of Screen main methods that every screen overrides.

public abstract int getLayout();

public boolean shouldShow()

public void populateData(View view)

public void onHide()

public abstract int getScreenIndex();

public boolean shouldCacheView()

public int getDuration()


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.