Question

I am working on a music synthesizer app and I would like to add a dynamic menu in the preferences where you can add as many instruments as you want.

When an instrument gets added/edited, I simulate a click to go back to the parent which lists all instruments and allow to add a new one again. To simulate the click, I use the code from this post: https://stackoverflow.com/a/4869034/1121352

However, I noticed that if I repetitively add/edit instruments, at exactly the 3rd click I get an out of memory error. BUT, if I do the same action, but I keep pressing the back button instead or reclicking on the add/edit instrument button, I get back to this preferencescreen anyway, and I can then add/edit instruments as much as I want without any error.

Thus it seems that when the back button history is too deep, it quickly gets out of memory.

Here is a snippet code of the xml to show the structure. There is no recursively generated structure, it's all laid down on the same level, so that when you press multiInstrumentsSubmit it goes back to multiInstrumentsScreen

<PreferenceScreen android:key="multiInstrumentsScreen" android:title="Multi Instruments" android:enabled="false">
    <PreferenceScreen android:key="multiInstrumentsAddScreen" android:title="@string/multi_instruments_add_screen_title_add">
        <ListPreference android:key="minstrument" android:defaultValue="@string/default_instrument" android:entryValues="@array/instruments" android:entries="@array/instruments" android:enabled="true" android:selectable="true" android:title="@string/prompt_instrument" android:summary="@string/summary_instrument"/>
        <EditTextPreference android:key="multiInstrumentsRange" android:enabled="true" android:selectable="true" android:title="@string/prompt_multi_instruments_range" android:summary="@string/summary_multi_instruments_range"/>
        <ListPreference android:key="mbaseNote" android:entryValues="@array/base_notes" android:defaultValue="@string/default_jammer_note" android:entries="@array/base_notes" android:title="@string/prompt_highest_note" android:summary="@string/summary_highest_note"/>
        <ListPreference android:key="mbaseOctave" android:entryValues="@array/base_octaves" android:defaultValue="@string/default_jammer_octave" android:entries="@array/base_octaves" android:title="@string/prompt_highest_note_octave" android:summary="@string/summary_highest_note_octave"/>
        <Preference android:key="multiInstrumentsSubmit" android:title="@string/add"/>
        <Preference android:key="multiInstrumentsDelete" android:title="@string/delete"/>
    </PreferenceScreen>
    <Preference android:key="multiInstrumentsSave" android:title="Save mapping"/>
    <Preference android:key="multiInstrumentsLoad" android:title="Load mapping"/>
    <PreferenceCategory android:title="@string/heading_multiInstruments" android:key="heading_multiInstruments">
        <!-- Entries will be dynamically added here, see Prefer.java -->
    </PreferenceCategory>
</PreferenceScreen>

Is there a way to clean up the back button history (deleting exactly 2 steps back would be perfect)? Or I am doing this wrong?

PS2: I already tried to debug and it's not because I dynamically construct my menus: even with this code commented out (the add instrument button does nothing but simulate a click), I get the same problem at exactly the same number of repetitions.

I also tried to analyze the memory heap using Memory Analyzer, but I got nothing interesting, which may make sense if it's a limit in the back button history and not in my app.

Was it helpful?

Solution 2

I have finally found a solution: it's possible to go back to the previous PreferenceScreen by just dismissing (.dismiss() method) the current one. This way, the dismissed PreferenceScreen doesn't add up to the history stack, and there's no overflow.

Here's an easy to use function to do just that:

// Close the current PreferenceScreen (or any given the name)
// Useful to go back to the previous PreferenceScreen when constructing dynamically nested submenus.
private void closePreferenceScreen(String prefScreenName) {
    PreferenceScreen prefScreen = (PreferenceScreen) findPreference(prefScreenName);
    prefScreen.getDialog().dismiss();
}

Note that you will have to specify an id for your PreferenceScreen, this is the string you'll give to this function.

More about this solution here: https://stackoverflow.com/a/26747403/1121352

OTHER TIPS

Take a look at the official documentation

You can't play with the backstack like it's an ArrayList, but you can indicate which activities should be saved in the backstack. You haven't provided any design details about your app, so I have no idea whether you will be breaking anything by adopting my suggestion, but your best bet is to just not add activities to the backstack at all by using the android:clearTaskOnLaunch flag.

If this solution breaks your navigation, then the proper way to deal with it is by improving your navigation so that users can get back to tasks or activities through menu options rather than relying on the backstack.

The fact that three activities results in OOM exception is also interesting. Perhaps your activities could use some trimming. Hard to say without seeing code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top