Question

I have a 2 preferences in my Settings: 1- PreferenceCategory 2-PreferenceX When I press PreferenceX, I add new preferences at runtime into PreferenceCategory. But when I rotate the device or kill my application then reopen it again: I can't find all the new preferences that I have at runtime. I tried to use saveHierarchyState & restoreHierarchyState for the given preferenceCategory but still can't make it work.

Here is a sample for my code:

my preferences.xml file:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:key="myCat"
        android:title="Example list"
        android:summary="This list is empty by default" />

    <Preference
        android:key="button"
        android:title="Example button"
        android:summary="When clicked this adds an item to the list" />

</PreferenceScreen>

Here is my MainActivity code:

package com.example.testpreferences;

import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;

public class MainActivity extends PreferenceActivity {

    private int counter=0;
    private PreferenceGroup  pg;
    /** Called when the activity is first created. */
    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);

       pg = (PreferenceGroup) getPreferenceScreen().findPreference("myCat");

        getPreferenceScreen().findPreference("button").setOnPreferenceClickListener(new OnPreferenceClickListener() {

            @Override
            public boolean onPreferenceClick(Preference a_preference) {


                Preference preference = new Preference(getApplicationContext());
                preference.setTitle("Item" + counter);
                preference.setKey("key"+counter);
                counter++;
                pg.addPreference(preference);

                return true;
            }
        });
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        pg.saveHierarchyState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle state) {
        if (null != state) {
            pg.restoreHierarchyState(state);

        }else
            super.onRestoreInstanceState(state);
    }
}

Try to rotate the device and you will the wrong behavior that I am describing. How can I keep the new preferences that are added during runtime to be shown upon screen rotation?

Was it helpful?

Solution

Rotate causes Activity restart.

When device is rotated, this happens.
onPause -> onCreate(with old savedInstanceState) ... -> onPause -> onCreate(newer savedInstanceState)

It means 2 activity reboot cycles (with differtent savedInstanceState) for 1 rotate.
(I've tried this code)

private int bootCounter = 0;

onCreate(...) { // watch savedInstanceState
    if (null != savedInstanceState) {
        bootCounter = savedInstanceState.getInt("bootCounter");
        bootCounter++;
    }
}

onSaveInstanceState(...) {
    ...
    outState.putInt("bootCounter", bootCounter);
}

maybe same problems:
Home key press behaviour
I haven't tested but there are some hints around #14, #17:
Issue26658:Activity stack confused when launching app from browser
long one, but many hints:
savedInstanceState always null


Alternation. (Use SharedPreferences to save preferences)

public class MainActivity extends PreferenceActivity
{
    private int counter = 0;
    private PreferenceGroup pg;

    /** Called when the activity is first created. */
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Load();

        getPreferenceScreen().findPreference("button").setOnPreferenceClickListener(new OnPreferenceClickListener()
        {
            @Override
            public boolean onPreferenceClick(Preference a_preference)
            {
                // Preference preference = new Preference(getApplicationContext());
                Preference preference = new Preference(MainActivity.this);
                preference.setTitle("Item" + counter);
                preference.setKey("key" + counter);
                counter++;
                pg.addPreference(preference);

                return true;
            }
        });
    }

    private void Save()
    {
        SharedPreferences sharedPreferences;
        Editor editor;
        Preference preference;
        int keyCount;

        if (null != pg)
        {
            sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
            if (null != sharedPreferences)
            {
                editor = sharedPreferences.edit();
                keyCount = pg.getPreferenceCount();
                // editor.putInt("keyCount", keyCount);
                // editor.putInt("counter", counter);
                for (int i = 0; i < keyCount; i++)
                {
                    preference = pg.getPreference(i);
                    editor.putString(preference.getKey(), preference.getTitle().toString());
                }
                // Save to file
                // *** commit() will block caller thread ***
                editor.commit();
            }
        }
    }

    @SuppressWarnings("deprecation")
    private void Load()
    {
        SharedPreferences sharedPreferences;
        Preference preference;
        Map<String, ?> data;

        addPreferencesFromResource(R.xml.preferences);
        pg = (PreferenceGroup) getPreferenceScreen().findPreference("myCat");
        counter = 0;
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        if (null != sharedPreferences)
        {
            // load from SharedPreferences
            data = sharedPreferences.getAll();

            // this doesn't keep original order
            for (Entry<String, ?> kv : data.entrySet())
            {
                if (String.class != kv.getValue().getClass())
                {
                    continue;
                }
                // fixed: getApplicationContext() causes style bug. (*1)
                // preference = new Preference(getApplicationContext());
                preference = new Preference(MainActivity.this);
                preference.setTitle(new String((String) kv.getValue()));
                preference.setKey(new String(kv.getKey()));
                preference.setEnabled(true);
                counter++;
                pg.addPreference(preference);
            }
            // counter = sharedPreferences.getInt("counter", counter);
            onContentChanged();
        }
    }

    //@Override
    //protected void onSaveInstanceState(Bundle outState)
    //{
    //    super.onSaveInstanceState(outState);
    //}

    @Override
    protected void onPause()
    {
        super.onPause();
        Save();
    }

}

(*1): fixed.
If getApplicationContext() is used to create Preference, items will be loaded but styles (or state) are incorrect. (If loaded item is touched, correct text is shown.)

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