I will try to explain a simple app scenario: My app goes right to a 'main view'. In this main view I have inserted a TextView which displays current settings created by way of the PreferenceManager. For simplicity sake, let's say I have a checkbox in my settings. When I first start my app - the TextView on my main view shows my checkbox setting correctly (true). Now I go to the settings menu, it pops-up, and then I change it to false. I go back to the main view and see no change. It still say's true even after I changed it to false. If I end the app and then re-start it - all is well and it shows my change.
Apparently the main view just stays in the background while I'm changing settings? How can I redraw or update the main view after I change settings?
You could implement OnSharedPreferenceChangeListener in your main Activity:
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (PREFKEY_OF_INTEREST.equals(key))
updateSomethingInMainView();
}
and in onCreate() call:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
When you go into your preferences your current activity should be paused and the resumed when you go back (see the lifecycle diagram on lifecycle diagram on the android site). You should be able to trigger some kind of redraw from within onResume() I would think. That will allow the data on the page to repopulate. Some sort of invalidate() call would do it I guess.
Related
Is anyone aware of the reason why my onDestroy method to save a bool inside my shared pref works fine on vd but doesn't always work on real device?
it looks like working when i quit the app and go back further to main screen but not when i quit the app, remain in the app list window and open the app back again.. weird
is there some bug i'm not aware of or may depend on my other classes? if so i can post the code but is very simple, just as said a bool save and a get
edit: if you guys try to create a scrollview in a fragment (frag of a MainActivity), and try to go on edit mode and press back button to quit your app, mess with it a few times and you'll see onDestroy and even onStop won't be called.
Q. So how am I supposed to save my pref before quitting an app in a consistent way? reliable all the times? also for this i'd need an onDestroy alternative not even onStop, cause I need to save pref only before app quit not on activity change, and since onDestroy isn't reliable (from what Android Dev guide says) what should I use??
thanks
WORKAROUND: I placed this in onCreateView()
boolPref = getActivity().getSharedPreferences("pref_bool", Context.MODE_PRIVATE);
firstVisit = boolPref.getBoolean("bool", DEFAULT);
if (firstVisit == false) {
scrollView.setVisibility(View.VISIBLE);
}else{
scrollView.setVisibility(View.INVISIBLE);
}
if (savedInstanceState == null) {
scrollView.setVisibility(View.INVISIBLE);
}
where firstVisit is boolean firstVisit; declared at start.
(this boolean trick was part of a solution from another post, but it didn't work well saved inside onDestroy() or onStop() cause sometimes they don't get called)
then I added this inside my button onClick:
boolPref = getActivity().getSharedPreferences("pref_bool", Context.MODE_PRIVATE);
SharedPreferences.Editor editor_bool = boolPref.edit();
editor_bool.putBoolean("bool", false);
editor_bool.apply();
scrollView.setVisibility(View.VISIBLE);
and it works, what it basically does is: set my scrollview to be hidden everytime my app starts (through savedInstanceState as #bwt suggested below), and remains hidden when i pass to another activity and come back (using bool = true) unless i press the button inside first activity (setting and saving bool == false) so from then on the scrollview is always visible even if i pass to another activity and come back
I think the right moment to save a preference is when it changes, not when the application quits. Specially since Android may choose to simply kill a process (and the included application) without calling any callback. Use apply() instead of commit(), so that the application does not have to wait.
Alternatively you can override onSaveInstanceState(). It is not part of the basic lifecycle but gives you the opportunity to store the current state of your Activity before being destroyed.
I am developing an application in which i am overriding the back button. I created a check box. On click of which i am calling intent for:
startActivityforResult();
And also maintaining the state of activity as :
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putBoolean("checkbox", checkbox.isChecked());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
checkbox_state = savedInstanceState.getBoolean("checkbox");
}
which run fine and the state is maintained.
Means i am entering value in edit text. and on check box click calling new activity for result and while return on first activity the state is maintain.
Now but from second activity if i click on device back button the state is not maintained.
So what should i do to maintain the state on back button. I searched but not found satisfied solution. Please suggest me.
When You start the new Activity then the current Activity gets hidden and new Activity is placed on top of the stack. Now if you press the back button on the new Activity then the first activity should come up in its current state (If it wasn't destroyed, calling finish()) where it was left i.e. if the check box was checked then it should remain checked. You don't need to save the activity state unless the orientation is changed or the activity is destroyed.
Are you sure you are not doing any thing in the onActivityResult or onResume() method which effects the state of the check box? I would recommend to first comment out all the code in both the methods and see if your check box retains the state. Also can you also make sure that the code itself doesn't uncheck the checkbox before starting the new Activity?
Now but from second activity if i click on device back button the state is not maintained.
onSaveInstanceState() is mostly used for configuration changes (e.g., rotating the screen).
So what should i do to maintain the state on back button
Most likely, there is no "state" that needs to be "maintained", outside of your data model. Your activity needs to update its data model: files, database, preferences, ContentProvider, some singleton that is your in-memory data model manager, whatever.
I have 2 Fragments. 1st is for calculation while the 2nd is for settings.
I save the settings using SharedPreference.Editor.commit() on onPause() method. No problem so far with the saving. The problem I am facing is retrieving the SharedPreference value on my 1st Fragment. I retrieved the value every time I pressed the count button. For the 1st time, the values I am getting are the ones before change (which is the problem I am facing), I will only get my saved value when retrieving/pressing the count button for the 2nd time or more.
And I try to change the settings and then press home button to terminate the app from outside (which triggers onPause method) and when I reopened the settings, the values did change to my defined settings. So, I am sure the settings did saved when onPause is triggered.
I wonder what is going wrong here. Any helps is much appreciated.
As requested, this is my saving code on my SettingFragment :
#Override
public void onPause() {
super.onPause();
saveToPref();
}
public void saveToPref() {
SharedPreferences settings = getActivity().getSharedPreferences("mysettings", 0);
Editor edit = settings.edit();
edit.putString("begin", String.valueOf(ibegin)).putString("end", String.valueOf(iend)).commit();
}
Initialize your SharedPreferences object somewhere else, and do it once - maybe in onCreate. The reason why you're not seeing the change is because a different instance of SharedPreferences is opened somewhere, with the same constructor, and multiple instances of these do not automatically resolve/merge. While you're at it, initialize the Editor edit instance along with settings.
Ok, I have found my problem. The problem is that onPause() is triggered only when I start another activity (I started an activity onClick of Button count). I changed my code to trigger the saveToPref() by overriding onPageSelected of my ViewPager and on backPressed of my MainActivity.
In my app, some settings can possibly be changed while the PreferenceActivity is not open, and an issue I'm running into is that addPreferencesFromResource is called in onCreate, so say, I open the PreferenceActivity, then go to another screen from there, then do something that changes the settings, then hit the back key to go back to the PreferenceActivity, then certain settings have not changed on the layout.
So, how could I re-load all the Preferences every time onResume (or onStart()) is called without duplicating the layout?
edit: This solution will work for API 11 + only.
Im not sure I fully understand your problem, but you could add a call to recreate() into the onResume of the activity which from my understanding has the activity go through the entire lifecycle again.
In order to make sure that you only do this when there is in fact dirty data, I would set a flag in the SharedPreferences that lets your activity know in the onResume() that it needs to be recreated.
public void onResume(){
super.onResume();
SharedPreferences pref = getApplicationContext().getSharedPreferences(Constants.PREFS_NAME, Context.MODE_PRIVATE);
if(pref.getBoolean("isDirtyPrefs", true))
recreate();
}
I had a similar problem. Failing to find a simple way to make my PreferenceActivity refresh itself, my solution was to add this to my PreferenceActivity:
/**
* Called when activity leaves the foreground
*/
protected void onStop() {
super.onStop();
finish();
}
This will cause the Prefs screen to reload from SharedPreferences next time it is started. Needless to say, this approach won't work if you want to be able to go back to your preferences screen by using the back button.
I have a PreferenceActivity with settings for my app and I want to refresh activity if some preferences was changed.
For example I have a checkbox which responsible for addtional tab in my layout, when checkbox is checked tab must be shown. To catch this event I used OnSharedPreferenceChangeListener. But this listener listen every click on this checkbox and do something (your logic) every time, every click even though setting really was not changed. I want to refresh my activity only if setting was really changed. If earlier was "OFF" and now become "ON" in this case I want to refresh, but if I changed OFF - ON - OFF I don't want to refresh.
How to catch really changes and how to handle this in activity?
Thanks!
How to catch really changes and how to handle this in activity?
Step #1: Implement the OnSharedPreferenceChangeListener on your main activity.
Step #2: Maintain a boolean data member, initially false, which you toggle whenever your checkbox of interest is changed.
Step #3: In onStart() or onResume(), if the boolean data member is true, refresh the activity and set the data member to false.