I am creating a simple survey app in android studio. I have multiple intents, and I start each one when the "next" buttons are pressed. I also have a back button that brings the user to the previous intent if they want to change an answer to a question. When I go forward again, none of the answers are saved. How can I get all the users answers to be maintained?
There are two methods you can override in your activities:
public void onSaveInstanceState(Bundle savedInstanceState);
public void onRestoreInstanceState(Bundle savedInstanceState);
As you see you have access to the Bundle "savedInstanceState". If a user terminates an activity onSaveInstanceState() gets called and you have the possibility to save data which you want to restore later.
The method onRestoreInstanceState() only gets called if you have saved information in onSaveInstanceState() and offers you the chance to restore that data. It provides a bundle which contains the same data that you saved into the data during onSaveInstanceState().
A bundle is basically a key-value list. To store a string for example you simply would call the putString()-Method of the bundle:
savedInstanceState.putString("myKey", "Hello World");
There are many data-types that you can store in a bundle (in general, every class that implements the interface Parcelable can be stored in a bundle).
More information:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
http://developer.android.com/reference/android/os/Bundle.html
How about using a singleton class for your data and store the intends there in a List or Array. You can extend the Application class for this or just make your own singleton class.
When your Activities are recreated they receive the callback onCreate(Bundle). Whatever you have saved in onSaveInstanceState(Bundle) will appear in Bundle.
You can implement a singleton class ,and use it in your application which extends Application.
Store your data to the singleton by map and provide getter and setter methods
Related
In onCreate(Bundle savedInstanceState), there`s already super.onCreate(savedInstanceState).
API says it restores states when create activity after destroyed.
But I have to override onSavedInstanceState(Bundle outState) for restore specific states.
Why?
What kind of informations are saved in savedInstanceState with method onCreate() and onSavedInstanceState()?
I'm so confused!
By default, when your device changes configuration (for example, devices rotates, you changed language settings, etc.), your foreground Activity is recreated, and all you Activity data is lost. For example, if you have a member variable mVariable that was assigned some value, after configuration change you will lose its value. That's why you need to save important data to savedInstanceState and re-init it from onCreate() method. You simply check whether savedInstanceState is not null, and if so, you init your values from savedInstance, else - init with default values.
Further reading: http://developer.android.com/training/basics/activity-lifecycle/recreating.html
onSaveInstanceState() is called before your activity is paused. So any info that it needs after it is potentially destroyed can be retrieved from the saved Bundle. The Bundle is a container for all the information you want to save. You use the put* functions to insert data into it. To get the data back out, use the get* functions just like the put* functions. The data is stored as a name-value pair. There isn't a specific use of this element, you can use it in any case (save a name, a number or whatever you need to have again when the use open again the app)
This is more of a structure/design philosophy question than anything.
I have main host activity that currently saves and loads profiles for viewing by the user.
The profiles' credentials are displayed within Fragment A (user name, birthday, etc). This is done by passing the profile as an argument to the fragment before using the fragment transaction to display it.
If the user leaves or rotates their screen, how should I go about saving that profile data? Should I do the saving from the onPause within Fragment A or its HostActivity?
And what if Fragment A also allows for profile editing? When the user confirms their changes, shall I let its HostActivity know to update the main profile being held from the activity?
Or would it be better to just wait until a FragmentA.onPause is called? I suppose I could wait until something forces the fragment to call onPause, at which point I can save both the state of the fragment as well as the profile activity from the host activity.
The main thing that confuses me is: Do I need to be managing two Profile objects? The HostActivity and its FragmentA both use it. It gets a bit confusing having to run back and forth between saving, loading, and editing. Can't I just handle all of this from one class?
Okay, I have two very good and viable answers. Which one is better for my purposes though? Should I use an sqlLite database or a global Java singleton to handle my profile? Only one profile can be active per session. Saving, loading, and editing of the profile must also be taken into consideration.
If there can only ever be one profile per user in one session (as you have suggested above) why not use a Java singleton class.
private ProfileOject() {
// Exists only to defeat instantiation.
}
public static ProfileObject getInstance() {
if(instance == null) {
instance = new ProfilerObject();
}
return instance;
}
Now use getters and setters as normal.
In each activity you can get the Profile like so:
profile = ProfileObject.getInstance();
This will mean that if you make an update in Fragment A, when the activity is called, it will fetch the updated values from the profile object.
In regards to onRotate/Pause/Resume use savedInstanceState, see example below:
//Use onSaveInstanceState(Bundle) and onRestoreInstanceState
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
// etc.
super.onSaveInstanceState(savedInstanceState);
}
//onRestoreInstanceState
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
}
Why don't you use a sqlite database for storing user profile data? Everytime you need access to user profile data you can just query it.
You can save all the relevant data in the onPause method. Using a database will ensure data persistence, resisting any fragment/activity recreation!
So I would like to save an arrayList of strings in onPause and get it back in onResume but the problem is I can't use sharedPreferences because my API level is 8 and I can't use the putStringSet function. Also, I would like to avoid saving data to the user's phone via a file system. I'm already doing that with several other things.
Is there any other way to save the data? I've tried putting a bundle in onPause and getting it in onResume and that hasn't worked, I've also tried implementing onSavedInstanceState and onRestoreInstanceState but those only get called when the activity is destroyed and I'm only putting it on pause most of the time.
make that arraylist static or create a singleton class for that
class data
{
public static ArrayList aa;
}
now on pause function
onPause()
{
data.aa=
}
this way you can have it maintained
You can use Modified Shared Preference to store your ArrayList. I was trying similar and I got answer for that. Here is the link. CustomSharedPreference
Here You can create one class with getter and setter for ArrayList and that class as a object in Shared Preference.
I have a problem with saving an instance on screen orientation change. I have an array with a specific structure:
private ArrayList <MyObject> myArr;
And this sctructure is:
public MyObject{
public variable1;
//..... many variables here and one array :)
}
I need to save "myArr" array. How can I save this "variable"?
Basically, instance should be saved, using the way, described in Android Activity API Ref: you need to use onSaveInstanceState(Bundle). Also, You can just set android:configChanges="orientation" in your manifest for an activity to prevent it's recreation (so where won't be any need for state saving presented).
To save objects from the question in onSaveInstanceState(Bundle) to the Bundle:
Implement Parcelable by MyObject (e.g. example can be found here etc.)
Put ArrayList in the bundle by putParcelableArrayList() in onSaveInstanceState() and get back by getParcelableArrayList() in onCreate() after rotation;
I was looking at the way Android handles orientation change for my application (I discovered that it restarts the mainactivity on orientation change. I've seen that you can override the method
protected void onSaveInstanceState(Bundle outState)
To save stuff, then have the in onStart. The problem is that I've my view with custom objects and a listview using a custom adapter. Everything is in a ArrayList of these objects, but I've noticed that you can't put arbitrary objects in the bundle! So how do I save the state?
Have you tried using: its work around ,
<activity name= ".YourActivity" android:configChanges="orientation|screenSize"/>
in Manifest file?
It does not work by default because , when you change the orientation onCreate will be called again and it redraws your view.
If you write this parameter no need to handle in Activity , the framework will take care of rest of things.
It will retain the state of the screen or layout if orientation is changed.
NOTE If you are using a different layout for landscape mode , by adding these parameters the layout for landscape mode will not be called.
Other way and Another way
EDIT: On newer versions of Android and with the compatibility library, retained fragments are usually the best way to handle keeping expensive-to-recreate data alive across activity destruction/creation. And as Dianne pointed out, retaining nonconfiguration data was for optimizing things like thumbnail generation that are nice to save for performance reasons but not critical to your activity functioning if they need to be redone - it's not a substitute for properly saving and restoring activity state.
But back when I first answered this in 2010:
If you want to retain your own (non view-state) data, you can actually pass an arbitrary object specifically for orientation changes using onRetainNonConfigurationInstance(). See this Android Developers blog post. Just be careful not to put any Views or other references to the pre-rotation Context/Activity in the object you pass, or you'll prevent those objects from being garbage collected and may eventually run out of memory (this is called a context leak).
First, you need to determine what is actually the "state" in your app. You haven't said what you are actually doing, but let me assume that the ArrayList of objects is the state the user is working with.
Second, decide what the lifecycle of this state actually is. Is it really tied to that activity? Or should the user not lose it if say their battery runs low, the device turns off, and they later return to your app? If the former, onSaveInstanceState() is correct; if the latter, you'll want to save to persistent storage in onPause().
For onSaveInstanceState() with custom objects, the key is to implement the Parcelable interface. This involves implementing the methods on Parcelable, as well as making a static CREATOR object in your class. Here's the code for a typical simple Parcelable class:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java
The key functions are the Parcelable implementation:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#317
and the CREATOR static class:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#355
(The static writeToParcel() and readFromParcel() are just conveniences that were done for that class and not required.)
Now that you have that, you can put your entire ArrayList of objects into the saved state Bundle with Bundle.putParcelableArrayList:
http://developer.android.com/reference/android/os/Bundle.html#putParcelableArrayList(java.lang.String, java.util.ArrayList)
In Activity.onCreate(), check to see if you have a savedState Bundle, and if so try to retrieve the ArrayList from that and use it if found, creating a new adapter and list view for the new activity that are used to display it.
but I've noticed that you can't put arbitrary objects in the bundle!
First make your custom objects Parcelable.
Then you can put them in to a bundle.
Everything is in a ArrayList of these objects
You can use putParcelableArrayList method in bundle to store an ArrayList of custom "parcelable" objects.
write your objects to JSON Strings using Google's Gson, then save them as a String. Then, build them back from the saved JSON Strings when rebuilding the Activity/Fragment
import com.google.gson.Gson;
public class MyClass {
private int a;
private String s;
private OtherSerializableClass other;
private List<String> list;
public String toJson() {
return new Gson().toJson(this);
}
public static ChatAPI_MessagesArray fromJson(String json){
return new Gson().fromJson(json, YourClass.class);
}
// Getters
...
// Setters
...
}