Android: Saving contents of a listview onSaveInstanceState - android

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.

Related

Can an activity be created with saved instance state saved by an older version of the app?

Could the savedInstanceState parameter passed to Activity.onCreate have been saved by a different version of the app? I can't find any reference to this in the documentation.
This could be theoretically possible if the activity was backgrounded, then killed due to low memory, then a new version of the app was installed, and then the user navigated back to the activity using the recents list.
In the example code below, could onCreate throw an ArrayIndexOutOfBoundsException or set a surprising state if the enum has been changed between versions, or is the code safe?
public class ExampleActivity extends Activity {
private enum State {
SOMETHING,
SOMETHING_ELSE,
ANOTHER_THING,
ET_CETERA,
}
private State state;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
state = State.values()[savedInstanceState.getInt("state")];
} else {
state = State.ANOTHER_THING;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("state", state.ordinal());
}
// ...
}
No. SavedInstanceState is not used to persist data across new instances of the same app. It is used to temporarily store data during the current app's 'session'.
In other words, the values you supply to the savedInstanceState bundle are stored when your activity is destroyed, for example, when you rotate the screen. These values are then retrieved when the activity is recreated.
When you quit the app entirely, or install a new version, these values are lost.
Theoretically always.
Before you upgrade (change) application. It deactivated and later starts over.
Now Android Studio added functionality "Instant Run", and in this case may possibly occur such an exception. More I do not have any ideas. It seems to me that such a check is not necessary right now. For all the time my development I've never encountered similar cases and have not heard about such an.

Getting null values when passing data from one activity to another in android

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

How to avoid getting the intent's extra to come back?

background
I have at least 2 activities on an app i've developing : a splash activity and a main activity. the splash activity calls the main activity.
on some cases (for now let's assume it's the first run only of the app) the splash activity adds a boolean extra (using intent.putExtra) to the intent to be true, and the main activity reads it using :
getIntent().getBooleanExtra(...,false);
the problem
i only wish to see the flag as true when i open the main activity after the splash activity.
This is why i've tried to just call (in the onCreate, right after i get the flag) :
getIntent().removeExtra(...);
another approach (acccording to this website) would be:
final Intent newIntent = new Intent();
setIntent(newIntent);
and another approach could be:
getIntent().putExtra(..., false);
none of those work: for some reason, on some cases, the flag is still returned as true.
as an example, i can press the home button (when the main activity was in the foreground), and then i start a heavy app (like the cut-the-rope game or a benchmark app), and then return to the app using the launcher.
in this case (which doesn't always occur), the splash activity isn't shown, but instead the main activity is shown. it calls onCreate again, while the flag itself is still set to true .
the question
why does it occur? how come the intent doesn't get reset?
is there a way to overcome this in an elegant way?
is it safe to just ignore the flag when the "savedInstanceState" is not null ?
It sounds like your VM is being torn down and re-started. I have observed on some devices that when the VM is re-created, instead of entering the launch activity, the last running activity is reconstructed from the saved state. It sounds like you are attempting to save state in the activity intent, so that is probably where your problems are coming from.
An important key to avoiding problems like this is to remember that the savedInstanceState bundle passed to onCreate is always null when the activity is being created new, in all other cases such as reconstructing after rotation or even when the VM has been torn down (as is likely your case) the savedInstance bundle passed to onCreate will be non-null.. my advice would be to use the intent to initialize your local state (the initial value of your flag) when the savedInstanceState is null, then never try to update your own intent, save your state in the savedInstance bundle..
E.G.
class Someactivity extends Activity {
private static final STATE_FLAG = "flagState";
private boolean someFlag;
protected void onCreate (Bundle savedInstanceState) {
final Intent intent = getIntent();
if(savedInstanceState==null) {
// Brand new, set from intent
someFlag = intent.getBooleanExtra(STATE_FLAG, false);
} else {
// Restored, set from saved instance
someFlag = savedInstanceState.getBoolean(STATE_FLAG, false);
}
}
protected void onSaveInstanceState (Bundle outState) {
// Save any updates to our activity state
outState.putBoolean(STATE_FLAG, someFlag);
}
}

Save instance of dynamically generated views when we switch back and forth between activities

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.

how to retain the state of activity in android

How do I retain the state of an activity in android? I have two layouts for portrait and landscape in layout and layout-land. I am loading the value from service at the time I am showing progress dialog. If loaded user rotates the device to landscape at the time also loading. How do I avoid that? user typed content in webview that also refreshed. How do I avoid that, can anybody provide an example?
Thanks
When orientation changes, the Activity is reloaded by default. If you do not want this behavior then add this to the Activity definition in your manifest:
android:configChanges="orientation|keyboardHidden"
For more detail, see Handling Runtime Changes
You can use the onRetainNonConfigurationChange() callback to store arbitrary data. It is called just before your application is about to be recreated.
Then, in onCreate() just check if some data were put aside by calling getLastNonConfigurationInstance() that returns the Object you put aside or null.
See this article on android developers.
Here's a sample borrowed from the link above:
#Override
public Object onRetainNonConfigurationInstance() {
//this is called by the framework when needed
//Just return what you want to save here.
return MyBigObjectThatContainsEverythingIWantToSave;
}
Automagic restore of previously saved state:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject MyBigObjectThatContainsEverythingIWantToSave = (MyDataObject) getLastNonConfigurationInstance();
if (MyBigObjectThatContainsEverythingIWantToSave == null) {
//No saved state
MyBigObjectThatContainsEverythingIWantToSave = loadMyData();
} else {
//State was restored, no need to download again.
}
...
}
When orientation changes, the Activity is reloaded by default. If you do not want this behavior then add this to the Activity definition in your android manifest file :
android:configChanges="orientation|screenSize|keyboardHidden"

Categories

Resources