Explain GoogleApi savedInstanceState - android

In the Google Api Example Code they have a very simple example on saving the state. I need this in order to deal with screen rotation.
My problem is that I do not understand where the methods getSavedText() and setSaveText() get called from. I put the debugger on them but it never gets triggered. The whole thing just works by "magic". What other things can I save? where do I find documentation explaining the magic
public class SaveState extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_save_state);
((TextView)findViewById(R.id.msg)).setText(R.string.hello_world);
}
CharSequence getSavedText() {
return ((EditText)findViewById(R.id.saved)).getText();
}
void setSavedText(CharSequence text) {
((EditText)findViewById(R.id.saved)).setText(text);
}
}
Link
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/SaveRestoreState.html
Alternate link
http://goo.gl/6TJy5

This Api Demo sample is bad one because it is confusing that you are expecting it will override onSaveInstanceState() method than use persisted state in onCreate() or onRestoreInstanceState() when you read the documentation, but it does not.
Firstly getSavedText() and setSavedText() methods are not used in this Save & Restore State activity. They are used/called in LocalSample Instrumentation example.
Forget these two methods you can erase them. Let's come to how this sample works; on background Android calls onRestoreInstanceState() and make all UI views persist their state to Bundle parameter of the method. Please debug the code and after rotating screen inspect savedInstanceState parameter in onCreate() method of this sample. You will see before rotation text of R.id.saved EditText in that Bundle. Main trick is that why one of EditText is saving its state and the other is not is because of freezesText attribute of EditText. freezesText attribute makes EditText/TextView save its state in onSaveInstanceState method. Please look here for more information about freezesText.
delete android:freezesText="true" or make it false from save_restore_state.xml or override onRestoreInstanceState method and do not call super.onRestoreInstanceState() and observe that it is loosing its state after rotation (configuration changes).
Note: You do not have to override onRestoreInstanceState method for this sample but for other requirements to save internal state of the Activity you have to.

Related

What is the different between to reinitialize data of Activity in onCreate() and onRestoreInstanceState() in Android

What is the different between to reinitialize data of Activity in onCreate() and onRestoreInstanceState()
I am getting bundle in oncreate aslo.So My question is why I am not able to set data in oncreate method while the same thing is done in onRestoreInstantstate..Then what is the use of bundle object in oncreate i went through different tutorial but not got relevant answer so please if any one know the difference that where does we use the implementation to reinitialize the data of activity that whether it should be in onCreate or onRestoreInstanceState................please let me know
#numan salati Said:
onRestoreInstanceState is redundant because you can easily restore state in onCreate.
Having said that here is what the official doc says for
onRestoreInstanceState:
Most implementations will simply use onCreate(Bundle) to restore their
state, but it is sometimes convenient to do it here after all of the
initialization has been done or to allow subclasses to decide whether
to use your default implementation.
So for best practice, lay out your view hierarchy in onCreate and
restore the previous state in onRestoreInstanceState. If you do that,
anyone who subclasses your Activity can chose to override your
onRestoreInstanceState to augment or replace your restore state logic.
This is a long way of saying onRestoreInstanceState serves as a
template method.
Here

creating a Parcelable which will be used inside the same activity

I've imported some JSON data and fetched it into a custom arrayList. The arraylist looks like this:
ArrayList<HashMap<String, String>> postList;
It all works fine, but if the orientation changes the whole JSON parse/fetch process will start over again. That's why I like to store my custom ArrayList.
I have found a lot of information about (how to use) the Parcelable interface, but they all cover sending data from activity A to B.
Can somebody please provide an example about how to use a Parcelable inside the same activity? Thanks in advance!
You should search online for onSaveInstanceState, it's a callback which is defined inside Activity class.
It works in the same way when you need to pass data between activites
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
}
Inside outState you will use normal Bundle methods to pass Strings, Integers and Parcelable values (putParcelableArrayList/putParcelable/putParcelableArray).
When the screen rotate or something happens (activity got destroyed etc.), this method could be called and when the activity gets recreated the bundle you used here will be passed to onCreate inside the savedInstanceState argument (the only argument of onCreate, Bundle).
Here inside onCreate you check if (savedInstanceState != null) to be sure you have a saved state, if it's true you use savedInstanceState.getParcelableArrayList (or something else, depends on what you want to get) to read back the list.
if (savedInstanceState != null)
{
ArrayList<Parcelable> parcelableArrayList = savedInstanceState.getParcelableArrayList("key");
}
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelableArray(myParcelableList);
}
It all works fine, but if the orientation changes the whole JSON parse/fetch process will start over again. That's why I like to store my custom ArrayList.
You mentioned that your orientation causes the whole process to restart in your Activity. Are you running the json... etc in your onCreate method? If that's the case, orientation changes cause onCreate to be called.
You can prevent onCreate from being called by modifying your AndroidManifest.xml to handle your own orientation changes for the current activity (look for the android:configChanges):
<activity
android:name="your.activity.package.andclass"
android:configChanges="orientation|screenSize">
<!-- etc -->
You might need to manually handle config changes for certain events, but I've never found it necessary.

Fragment state lost when device left idle

Fragment losing state and shows an empty UI if left idle for 20 minutes. I'm using FragmentStatePagerAdapter and I have tried calling the notifyDataSetChanged in onStart() of my FragmentActivity.
Kindly help me how to save the object and state of my fragment and reuse it on reload of the app.
Android can kill your app if needed, you need to use onSaveInstanceState to keep your state in this cases. (Remember: Save important data in onPause!)
onSaveInstanceState exists in Activity and Fragments and is used in the same way like an activity
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("integer", anInteger);
}
Now in onCreate, onCreateView or onActivityCreated you have this argument BundlesavedInstanceState which corrisponds to the bundle saved. (Check if it's null too.)
If not enought maybe Android killed your FragmentManager too, so you need to override onSaveInstanceState and onRetoreInstanceState in your Activity and restore the fragment.
Maybe this answer could help you about the last thing i said: Using onSaveInstanceState with fragments in backstack?
A Fragment's life-cycle is closely tied to the Activity's lifecycle. This means, when your Activity goes idle; it will kill off any contained Fragments. To store Fragments you could always retain them in concordance with the Fragment API. This means you will generally be using the Fragment in a background. However the best way to keep a from being destroyed or lost from an Activity's end would be to store relevant information in a custom object and then to recreate the Fragment when the Activity is resumed.
For instance; I could have a custom object that would store relevent UI values for my Fragment and when my Activity either idles or changes I would save those relevant values to my custom object that I created. Then, when either a new Activity is created; or my old Activity is resumed; I would retrieve those values and put them back into my Fragment's UI. Hoped this helped :)
In case android needs memory, it kills the running apps. So you must save the objects using
public void onSaveInstanceState(Bundle savedState) {}
Note that savedState must be serializable.
You must call notifyDataSetChanged() in onResume(), because it ensures that it is called when the activity resumes.
For a detailed answer, please post your code.
Hard to answer without your code.
However I can say that the state is usually saved by the savedInstanceState
Usually in the onActivityCreated you have something like the following. In the example I give I save a boolean of either text was entered or not.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mHasText = savedInstanceState.getBoolean(HAS_TEXT_TAG);
} else {
// do something
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(HAS_TEXT_TAG, mHasText);
}
it's just an example as without your code it's difficult to anwer

Android onSaveInstanceState and starting sub-activities.

I have an app which has a main activity that calls other activities on a button press.
The main activity hosts a class which contains a lot of data and is parcelable. the data is the backbone for the application and I need to save it across orientation changes. In order to achieve this it use onSaveInstanceState and put the parcelable object in the bundle.
However, I have noticed that onSaveInstanceState is called everytime i press a button and start one of the new activities as well as on orientation changes. This is slightly slowing down the transition to the other screens.
Is there a good way to only store this information when I know for definite that the activity will be destroyed rather than every time I navigate away from the Activity periodically. I understand that the minute I navigate away from the main activity there is a chance that it may get destroyed.
Thanks,
M<
For primitive values, you should use onSaveInstanceState. For restoring you can use onRestoreInstanceState or you can some code in onCreate like this:
if(savedInstanceState != null) {
// restore old state
} else {
// a fresh start
}
Now for restoring big objects like Bitmap etc if they are not expensive to create and doesn't make your UI sluggish, create them again on restore. If you do not want to that then use onRetainNonConfigurationInstance and code will look like this:
#Override
public Object onRetainNonConfigurationInstance () {
return bmp;
}
#Override
public void onCreate() {
bmp = (Bitmap)getLastNonConfigurationInstance();
}
WARNING: This api is deprecate, you might use it on old platforms. I put it here for illustration purpose. The new way to do this is more involving.
Here is detailed ref:
getLastNonConfigurationInstance
onRetainNonConfigurationInstance
Recommended soln for new api levels 11 and above:
"Use the new Fragment API setRetainInstance(boolean) instead; this is also available on older platforms through the Android compatibility package." snippet from the doc when you click on the links above.
So, you will create your bitmaps inside the fragment and call setRetainInstance on fragment so that fragment and its content (in your case bitmap) will be retained accross config change.
Ref:
setRetainInstance

Android app resets on orientation change, best way to handle?

So I am making a basic chess app to play around with some various elements of android programming and so far I am learning a lot, but this time I am lost.
When the orientation of the emulator changes the activity gets reset. Based on my research the same thing will happen anytime the application is paused/interrupted, ie. keyboard change, phone call, hitting the home key etc.
Obviously, it is not viable to have a chess game constantly reset, so once again I find myself needing to learn how to fix this problem.
My research brings up a few main things, overriding the onPaused method in my Activity, listening for Orientation, Keyboard changes in my manifest (via android:configChanges), using Parcelables, or Serialization.
I have looked up a lot of sample code using Pacelables, but to be honest it is too confusing. Maybe coming back tomorrow with fresh eyes will be beneficial, but right now the more I look at Parcelables the less sense it makes.
My application utilizes a Board object, which has 64 Cell Objects(in an 8x8 2D array), and each cell has a Piece Object, either an actual piece or null if the space is empty. Assuming that I use either Parcelable or Serialization I am assuming that I would have to Parcelize or Serialize each class, Board, Cell, and Piece.
First and foremost, is Parcelable or Serialization even the right thing to be looking at for this problem? If so is either Parcelable or Serializable preferred for this? And am I correct in assuming that each of the three objects would have to be Parceled/Serialized? Finally, does anybody have a link to a simple to understand Parcelable tutorial? Anything to help me understand, and stop further headaches down the road when my application expands even further.
Any help would be appreciated.
in your manifest in the <Activity> tag, you can add android:configChanges="orientation|keyboardHidden", this will stop the activity from reloading and call onConfigurationChanged() instead when the orientation is changed or the keyboard is hidden.
If you need to make adjustments when either of these events happen, you can override onConfigurationChanged() in your activity, if not all you have to do is add the property to the manifest.
Something like:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}
works perfectly well.
Androids default way of handling the events is to recreate the activity. Basically you handle one process correctly and everything works, no need to worry about handling those things manually.
The Application Fundamentals has a complete overview of the activity life cycle, but in short you want to save your activity state in the onSaveInstanceState() method and use the Bundle you get in the onCreate(Bundle savedInstanceState) to restore your application state.
If you want to store your classes in the Bundle your best bet is to implement the Parcelable interface. Then to save your state you do:
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelable("yourObject", mYourObject);
}
and in the onCreate method you simply do:
if (savedInstanceState != null)
mYourObject = savedInstanceState.getParcelable("yourObject");
Of course you could just convert your objects into normal array representations that the Bundle can already contain and just skip implementing the Parcelable interface. Basically add a method toArray() to your object and a static method fromArray(). Well, play around and see which suits you better.
Or stick this line in your OnCreate so it doesn't roate. Problem solved.
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Override onRetainNonConfigurationInstance in your Activity class.
In this method you must return an object, just bundle up your game's state in a single state object and return it in this method. Make sure this is only a state object, by that i mean it should have no handles to an activity, view, etc. contained within it or you'll get memory leaking.
In your onCreate method call getLastNonConfigurationInstance to get the object back.
You don't have to worry about the implementation details (the serialization) android takes care of that.
If you haven't already make sure you've set your Launch Mode in the manifest to either singleTask or singleInstance depending on which fits your needs better. By default if someone hits home and then comes back to your application it launches a new copy of the activity, if not handled or configured for single instance you'll get multiple copies of your game activity running.
When you save the board state, make an int[64] and at each position store the corresponding piece. So 0=empty, 1=white pawn, 2=white knight, etc...
When you load the board state, iterate through the array and create the appropriate piece objects at the appropriate locations.
You can convert the int[64] to a string to store in SharedPreferences, or use it with a Parcelable or whatever. Only store the minimum data you need.

Categories

Resources