I have set a value in spinner , from activity-1.
now i am traversing to activity-2 and again coming back to activity-1, i am not getting the updated spinner value which i have selected previously but i am getting default value(value at index 1) of spinner .
An Activity that becomes inactive (invisible to a user) can be destroyed by the system in case of lacking resources. To keep values between Activity runs you need to save your state using Bundles. If you look closely to Activity::onCreate method you can see it has a parameter:
protected void onCreate (Bundle savedInstanceState)
So, eg in method onPause() you save your desired values and when Activity is recreated - load them.
Android documentation contains a chapter how to save states between Activity runs.
Related
The first time my android app is launched I bring up a preferencefragment because the user needs to initially make a selection from a list of items and their selection needs to be saved. I extend ListPreference to display the list of items.
The way it should work is the user selects an item from the presented list. This selection
gets saved in SharedPreferences and the app transitions to another fragment. All of this is
working, but for some reason the ListPrefence gets display a second time.
I've put in some logging and discovered that for some reason two ListPreference object are
being constructed...but I know of only one call to create it. I'm somehow missing where/why
the ListPreference constructor is called a second time.
My PreferenceFragment code is simple. It looks like
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("INIT", "ONCREATE");
addPreferencesFromResource(R.xml.inititems); // load from XML
There's only the addPreferencesFromResource() call. No other place in my fragment code
should (as far as I understand) cause the ListPreference to be instancitated, but
the logging tells me the ListPreference constructor is called twice and the fragment's
onCreate is called just once.
I'm going to try to do a stack trace from the ListPreference constructor, but I wanted to
see if anyone here has thoughts or suggestions beyond the stack trace. Why would the
constructor be called twice ?
Thanks!
-Mar
You possibly have referenced the fragment in your layout resource file using android:name="yourfragment" as well as at run-time in onCreate(). That would cause it to be loaded twice.
I am storing some data in static varibles in Activity1 and accessing in Activity3,and Activity 5. ie..
Activity1---> Activity2--->Activ3
.....................|
......................Activity4.-----> Activ5
This works fine if we close the application completely, from Activity1 (ie if the user is at Activ5 if he clicks back button then -->Activ4-->Activ2-->Activ1-->Exit)
But the user is exiting app at Activ3,4,5 by clicking Mobile exit button(Not the application exit), Now after few hrs the user is reopening application then , It(app) gets started from Activi3 or 4 or 5. (ie where ever app was closed).
Now, Since i am using some data(which i stored in static varibles in Activ1.)
I am getting null values. Why this is happining. How to avoid this types of errors.
I have used sharedpref to avoid this.Is this the only solution ?
Restore the state of activity when it is recreated, so that the values passed can be retrieved at a later time.
e.g. for an integer that was passed through intent do as following: -
//this will save the value if an activity is killed in background.
#Override
protected void onSaveInstanceState(Bundle outState)
{
getIntent().putExtra("count", getIntent().getStringExtra("count"));
super.onSaveInstanceState(outState);
}
//In restore instance state, retrieve the stored values. The following work can also be done //in oncreate, as when an activity is killed in background, onCreate method is also called.
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
if(savedInstanceState == null)
return;
int count = getIntent().getIntExtra("count", 0);
super.onRestoreInstanceState(savedInstanceState);
}
You need to add onSaveInstanceState methods to your earlier activities, and check the bundle received by the onCreate methods. Check out the Activity Lifecycle for details.
You should not store values in static members, the activity context gets released, thus you losing your static values. The preferred way of passing values between activities is using Bundles along with the Intents.
you can create new class and extend application ,and in that store all data that you want, its very useful but remember if you do that you must add name of your application in manifest file
I am inflating a view on button click and the user can add as many views as he likes, all is fine I made it work, but now the problem is when I go back one activity and come again to my dynamically generated activity every single view that was generated is gone. Similar is the case if I go to next activity and come back to the inflated activity. I know about onSaveInstance and onRestoreSaveInstance. But how do I put view information in a bundle in onSaveInstanceState? Please note that my view was generated Dynamically i.e. on button Click and I want to know as of how to preserve the state of my activity.
How do you go about it?
I am thinking that you should implement some kind of logic that helps you restore the state of your Views. So you should be designing a class, let say ViewDetail that somehow keeps details about the Views that you are adding.... type, dimension, etc. This class should implement Parcelable so you are able to add it to the bundle.
So you will keep an ArrayList<ViewDetail>, myViews where everytime the user adds a new View you create a new ViewDetail object that you add to your myViews array.
And then save your Views and restore them using those objects:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//save your view states
outState.putParcelableArrayList("MY_VIEWS",myViews);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//get the views back...
myViews=savedInstanceState.getParcelableArrayList("MY_VIEWS");
//TODO: add the views back to your Activity
}
As your application may be killed completely at any moment without noticem you have to provide long term storage off heap memory
You only have to restore all the views, if your activity was terminated (and it can be at any time). When it is activated again after termination, it goes through onCreate() method
- this would be proper place to restore activity state.
Only callback which is guaranted to be called before your application / activity is destroyed is onPause() - this is a proper place to save views states into long term off-heap storage.
I have seen the following links before posting this question
http://www.devx.com/wireless/Article/40792/1954
Saving Android Activity state using Save Instance State
http://www.gitshah.com/2011/03/how-to-handle-screen-orientation_28.html
How to save state during orientation change in Android if the state is made of my classes?
I am not getting how should i override the following function :
#Override
public Object onRetainNonConfigurationInstance() {
return someExpensiveObject;
}
In my application i have layout with one editext visible and other editext get visible when the data of first editext validates to true.I have set the visbility of all other editextes and textviews to false and make them visible after validating.
So in my activity if the screen orientation is changed then all the items having android:visibility="false" get invisible.
I have also came to know that when our activities screen orientation changes it calls onStop() followed by onDestroy() and then again starts a fresh activity by calling onCreate()
This is the cause .. But i am not getting how to resolve it ..
Here You can see the screenshots of my application :
in this image all fields are loaded
and in another image when the screen orientation is changed to landscape they are all gone
Any link to tutorial or piece of code will be highly appreciable.
And also my application crashes when a progress dialog is shown up and i try to change screen orientation.How to handle this ??
Thanks
Well if you have the same layout for both screens then there is no need to do so just add below line in your manifest in Activity node
android:configChanges="keyboardHidden|orientation"
for Android 3.2 (API level 13) and newer:
android:configChanges="keyboardHidden|orientation|screenSize"
because the "screen size" also changes when the device switches between portrait and landscape orientation.
From documentation here: http://developer.android.com/guide/topics/manifest/activity-element.html
There is another possibility using which you can keep the state as it is even on Orientation change using the onConfigurationChanged(Configuration newConfig).
Called by the system when the device configuration changes while your activity is running. Note that this will only be called if you have selected configurations you would like to handle with the configChanges attribute in your manifest. If any configuration change occurs that is not selected to be reported by that attribute, then instead of reporting it the system will stop and restart the activity (to have it launched with the new configuration).
At the time that this function has been called, your Resources object will have been updated to return resource values matching the new configuration.
There are 2 ways of doing this, the first one is in the AndroidManifest.xml file. You can add this to your activity's tag. This documentation will give you an in depth explanation, but put simply it uses these values and tells the activity not to restart when one of these values changes.
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
And the second one is: overriding onSaveInstanceState and onRestoreInstanceState. This method requires some more effort, but arguably is better. onSaveInstanceState saves the values set (manually by the developer) from the activity before it's killed, and onRestoreInstanceState restores that information after onStart() Refer to the official documentation for a more in depth look. You don't have to implement onRestoreInstanceState, but that would involve sticking that code in onCreate().
In my sample code below, I am saving 2 int values, the current position of the spinner as well as a radio button.
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
spinPosition = options.getSelectedItemPosition();
savedInstanceState.putInt(Constants.KEY, spinPosition);
savedInstanceState.putInt(Constants.KEY_RADIO, radioPosition);
super.onSaveInstanceState(savedInstanceState);
}
// And we restore those values with `getInt`, then we can pass those stored values into the spinner and radio button group, for example, to select the same values that we saved earlier.
#Override
public void onRestoreInstanceState(#NotNull Bundle savedInstanceState) {
spinPosition = savedInstanceState.getInt(Constants.KEY);
radioPosition = savedInstanceState.getInt(Constants.KEY_RADIO);
options.setSelection(spinPosition, true);
type.check(radioPosition);
super.onRestoreInstanceState(savedInstanceState);
}
Is there an built in way to save the contents of a listView as part of onSaveInstanceState to then restore later? I want the listView to look the same if the user hit the back button and now onCreate is being called again.
If you set your activity's launchMode to singleTask, then (unless the application was terminated / gc called upon) your data (list) will be preserved.
This way your device will hold only one running instance of your application at a time, so when you "launch it again" no matter from where, if it's already running in the background, then that instance will show up (with the latest data).
If there is a risk that your application was finished, and you still need the latest list of data to show up, this solution won't work.
But you could give a try to SharedPreferences: save the current data to the application's SharedPreferences, and restore it from there when launching it.
If it's ok, to have the predefined new list on each clean start of the application, but when getting it into foreground, you need the last seen items in your list, you should use the savedInstanceState parameter of your onCreate method:
private static final String MYLISTKEY = "myListLabels";
private ArrayList<String> listLabels = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState.containsKey(MYLISTKEY))
{
listLabels = savedInstanceState.getStringArrayList(MYLISTKEY);
}
else
{
// TODO: populate explicitely your list
}
}
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putStringArrayList(MYLISTKEY, listLabels);
}
where listLabels contains the labels for your list.
It's not necessary for them to be of type String, you can put any type inside your Bundle.
When the user hits the back button the activity is always destroyed, so there will not be any restoring from savedinstance.
Android Training
When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed.