Sunday, June 3, 2018

Android runtime Preferences are lost on device rotation



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:




xmlns:android="http://schemas.android.com/apk/res/android">


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

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





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?


Answer



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 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 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.)


No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...