Mandatory calling superclass methods of an Android activity? - android

In the life cycle of an activity, is needed to call to methods of parent class always? .What I mean is:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onStart() {
super.onStart();
}
protected void onResume() {
super.onResume();
}
protected void onPause() {
super.onPause();
}
protected void onStop() {
super.onStop();
}
protected void onDestroy() {
super.onDestroy();
}
protected void onRestart() {
super.onRestart();
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
And do I always have to call the super class method first? For example:
public void onSaveInstanceState(Bundle outState) {
.....my code.......
super.onSaveInstanceState(outState);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
.......my code......
}
On onSaveInstanceState method it has more sense to write my code first and after to the superclasss method and on onRestoreInstanceState method the opossite?
Thanks

The documentation for the lifecycle methods indicate if calling super.onXXX() is required or not. For some methods this is required, for some it is not.
For the lifecycle methods which require calling through to super.onXXX(), you can call that method at any time. It can be before or after your code.
For onSaveInstanceState() and onRestoreInstanceState(), it should also make no difference whether you call super.onXXX() before or after your code. Hopefully, the stuff that you put in the saved instance Bundle does not conflict with the stuff that the Android framework is putting in the Bundle. If it conflicts, you'll have a problem no matter whether you call the super method before or after your code.
NOTE: The Android framework uses the following keys when putting View and Dialog information in the saved instance Bundle:
static final String FRAGMENTS_TAG = "android:fragments";
private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
private static final String SAVED_DIALOG_ARGS_KEY_PREFIX = "android:dialog_args_";
so as long as you don't use keys with the same names, you should be good.

Related

Button savedInstanceState and onRestoreInstanceState

Saving the State of Drawable xml Button.
private boolean mJam;
private button mSwitch;
private static final String KEY_ENABLE = "KEY_ENABLE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if( null == savedInstanceState ) {
mJam = false;
} else {
mJam = savedInstanceState.getBoolean(KEY_ENABLE);
}
button_layout();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_ENABLE, mJam);
outState.putBoolean(KEY_ENABLE, mSwitch.isSelected()); // Saving the state of the
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
mSwitch.setSelected(savedInstanceState.getBoolean(KEY_ENABLE));
mJam = savedInstanceState.getBoolean(KEY_ENABLE);
super.onRestoreInstanceState(savedInstanceState);
}
Note: If you don't want to use ScreenSize in Android manifest, This code can be used,
If you want to do it Manually, then go for this one.
P.S: setting Screen Size in Manifest, never go to onCreate if the Orientation Change, It Just saved all the instance and display as it is, when
Android orientation Change.

restoring state in a presenter with MVP

https://medium.com/#cervonefrancesco/model-view-presenter-android-guidelines-94970b430ddf says to restore state in the model instead of the presenter. What if I have a very simple "model", say a binary toggle that updates a textview to be on or off? Creating a model Toggle class that has a single string value seems like overkill.
Another option is to pass the bundle from my Activity into a corresponding method in my presenter inside onSaveInstanceState and restore it similarly with onCreate. But the article also says that we should avoid having android dependencies in the presenter.
Finally I tried using Icepick but this did not work:
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
(Button) findViewById(R.id.btn).setOnClickListener(this);
presenter.onCreate();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
}
#Override
public void onClick(View view) {
presenter.onButtonClicked();
}
#Override
public void updateState(String state) {
tv.setText(state);
}
MainPresenter.java
public class MainPresenter {
private MainView mainView;
#State String toggle;
#Inject
public MainPresenter(MainView mainView) {
this.mainView = mainView;
}
void onCreate() {
mainView.updateState(toggle);
}
void onButtonClicked() {
mainView.updateState(toggle.equals("on") ? "off" : "on");
}
}
What are my options? If I have to use the model approach can I see an example of this for my case?
If you're using annotation processing to maintain the state, it won't automatically populate data into your presenter without Icepick.saveInstanceState(this, outState) which you can't call in the presenter.
#State String toggle;
This line should be present in the activity. Have a method in your presenter to request data by toggle. Something like this:
#State String toggle = "off"; //default value
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
(Button) findViewById(R.id.btn).setOnClickListener(this);
presenter.onCreate();
presenter.setState(toggle)
}
You can store this value as the global variable in the presenter and decide the app flow accordingly.

Do I have to call EasyTracker.getInstance(this); everytime I need the easyTracker?

Do I have to call EasyTracker.getInstance(this); everytime I need the tracker or can I only initialize in onCreate() and from then on store it as a private field like this?
public class AndroidStarter extends Activity
{
private EasyTracker easyTracker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
easyTracker = EasyTracker.getInstance(this);
}
#Override
public void onStart() {
super.onStart();
easyTracker.activityStart(this);
}
#Override
public void onStop() {
super.onStop();
easyTracker.activityStop(this);
}
}
You can do it either way.
The advantage of your way is that you don't have to call getInstance(). This might be very very very slightly faster.
The advantage of calling getInstance() each time is that if the Tracker isn't getting used for a while because you're in the same Activity for a while, the Tracker could get garbage collected to free up memory.

how to store values and retrieve it when the orientation changes?

I have checked many posts, and as per that I have done coding for the orientation change. When orientation changes, the problem is I am not able to retrieve the entered values inside TextViews. Can anyone plz tell where did I go wrong?
Coding:
In manifest file for the corresponding activity I added:
android:configChanges="orientation|keyboardHidden"
In activity, I added the following methods:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_screen);
//Initialized the widgets
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//have written separate layout files for portrait and landscape
setContentView(R.layout.home_screen);
//Initialized the widgets again
retrieveSavedState(); //sets the TextViews again
}
#Override
protected void onPause() {
super.onPause();
saveState(); //save the TextView values
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState();
}
#Override
protected void onResume() {
super.onResume();
retrieveSavedState();
}
#Override
public Object onRetainNonConfigurationInstance()
{
final MyDataObject data = collectMyLoadedData();
return data;
}
the above method can be used to save any object to save data...
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data == null) {
data = loadMyData();
}
...
}
and u can retreive that object in the onCreate() which will we called when orientation changes.. after reading data from that object you can use it where ever you want..
http://developer.android.com/guide/topics/resources/runtime-changes.html
http://developer.android.com/guide/topics/resources/runtime-changes.html
other mechanisms are also there but this is the best way for my knowledge.. you can also use shared preferences to store and retrieve data...
http://saigeethamn.blogspot.com/2009/10/shared-preferences-android-developer.html

Android: Fatal Exception (NotSerializableException) when quitting an activity that serializes objects in onSave/onRecall

I am developing an app that uses some custom classes as members.
I have implemented serialization/de-serialization in the onSaveInstanceState and onRestoreInstanceState methods.
It all works fine when rotating the screen (app is destroyed and re-created) and my objects are restored.
However, when pressing the home button, the app crashes in the onPause method (which I have not modified)...
Any clue as to what's happening?
Here's a code sample that reproduces the issue
import java.io.Serializable;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class InvestigateError extends Activity {
private static final String LOG_TAG = "MYERROR";
protected ShowInfo myShowInfo;
protected class ShowInfo implements Serializable
{
private static final long serialVersionUID = 1L;
public String title;
}
public void populateMembers()
{
myShowInfo = new ShowInfo();
myShowInfo.title = "Was I serialized???";
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if(savedInstanceState == null)
populateMembers();
Log.d(LOG_TAG,"Activity created");
}
/* Save members */
#Override
public void onSaveInstanceState(Bundle outState) {
Log.d(LOG_TAG,"__ SAVEINSTANCE __");
outState.putSerializable("myshowInfo", myShowInfo);
super.onSaveInstanceState(outState);
}
/* Restore members */
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(LOG_TAG,"__ RECALLINSTANCE __");
myShowInfo = (ShowInfo) savedInstanceState.getSerializable("myshowInfo");
Log.d(LOG_TAG,"string from object: " + myShowInfo.title);
}
#Override
protected void onDestroy() {
Log.d(LOG_TAG,"__ DESTROY __");
super.onDestroy();
}
#Override
protected void onPause() {
Log.d(LOG_TAG,"__ PAUSE __");
super.onPause();
}
#Override
protected void onStop() {
Log.d(LOG_TAG,"__ STOP __");
super.onStop();
}
}
Here's the beginning of the stack trace
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.esquared.InvestigateError.InvestigateError$ShowInfo)
at android.os.Parcel.writeSerializable(Parcel.java:1160)
at ndroid.os.Parcel.writeValue(Parcel.java:1114)
at android.os.Parcel.writeMapInternal(Parcel.java:479)
...
You have 3 choices:
Make the outer class serializable as well.
Make your serializable inner class static.
Create another class and make that class serializable (don't serialize an inner class).
First one is actually discouraged.
And as Mayra mentioned, it will work faster if you implement Parcelable.

Categories

Resources