onCreate(...) is called twice after the device is rotated
Asked Answered
C

6

12

I have a question about rotating the Android device. My code logs a static and non-static attribute in onCreate(...).

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {
    static int sn;
    int n;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sn++;
        n++;

        Log.i("onCreate", String.format("sn=%d n=%d", sn, n));
    }
}

The screen orientation is portrait. When I first ran the code, I got:

onCreate(): sn=1 n=1

After I rotated the screen to landscape, I got:

onCreate(): sn=2 n=1

After I rotated the screen again to portrait, I got:

onCreate(): sn=3 n=1
onCreate(): sn=4 n=1

My questions are:

  1. How can I prevent onCreate(...) to be called twice when the device is rotated back to portrait?
  2. How can I save the value of non-static variable when the device is rotated?
Cosset answered 7/11, 2011 at 3:33 Comment(1)
#456711Nildanile
T
10

Whenever the screen orientation is changed, that Activity is destroyed and a new activity starts by onCreate() method. so every time you rotate the screen that activity will be destroyed and a new activity starts by onCreate() method. You can save Non Static member by overriding onSaveInstanceState(Bundle b) method. Android calls this method whenever the screen is rotated, and that given bundle b would be passed to oncreate(Bundle b) from which you can extract your non static member.

Tavel answered 7/11, 2011 at 3:41 Comment(4)
I overrided onSaveInstanceState(Bundle savedInstanceState) but it was not called when I rotated my emulator.Cosset
you may not have properly ovverided the method, it is called just before onPause().Tavel
@Override protected void onSaveInstanceState(Bundle bundle1){ super.onSaveInstanceState(bundle1); Log.i(tag,"inside onSaveInstanceState"); bundle1.putInt("variable n",n); bundle1.putInt("sn",sn); }Tavel
I know the reason why I cannot see my log message in onSaveInstanceState(...). It is because the tag` parameter in Log.i(tag, msg)` is too long. Thank you very much for your reply.Cosset
J
32

This is a known issue in the emulator (see the discussion here). It's not a bug, but it is an issue for many people going back years. As I understand it, the basic problem is that your activity is restarted twice when it goes into portrait mode because the emulator is handling two configuration changes separately: the orientation change itself and the deactivation of the keyboard. It doesn't happen in the other direction because there isn't a configuration change event corresponding to activation of the keyboard. (I find this strange, but evidently this is the desired behavior for some reason.)

In any event, the solution seems to be this to add this to your activity manifest declaration:

android:configChanges="keyboardHidden|orientation"

If you actually require those changes to load new resources, you can manually handle it in onConfigurationChanged.

Joyann answered 7/11, 2011 at 4:6 Comment(5)
+1; interesting. I'd never even noticed it was called twice (or if it should matter if it is).Pretender
+1: noticed it on the emulator but never bothered me testing with a real device (going back to 1.6/2.x days). Haven't relied on the emulator since.Donella
I had to use this to cover all bases: keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSizeCremona
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" I've added. thanks.Robot
Not only for emulator, its also behaving the same on real device, as well as, configChanges not working out for me :(Sorehead
T
10

Whenever the screen orientation is changed, that Activity is destroyed and a new activity starts by onCreate() method. so every time you rotate the screen that activity will be destroyed and a new activity starts by onCreate() method. You can save Non Static member by overriding onSaveInstanceState(Bundle b) method. Android calls this method whenever the screen is rotated, and that given bundle b would be passed to oncreate(Bundle b) from which you can extract your non static member.

Tavel answered 7/11, 2011 at 3:41 Comment(4)
I overrided onSaveInstanceState(Bundle savedInstanceState) but it was not called when I rotated my emulator.Cosset
you may not have properly ovverided the method, it is called just before onPause().Tavel
@Override protected void onSaveInstanceState(Bundle bundle1){ super.onSaveInstanceState(bundle1); Log.i(tag,"inside onSaveInstanceState"); bundle1.putInt("variable n",n); bundle1.putInt("sn",sn); }Tavel
I know the reason why I cannot see my log message in onSaveInstanceState(...). It is because the tag` parameter in Log.i(tag, msg)` is too long. Thank you very much for your reply.Cosset
P
3

Don't know about the onCreate issue; those calls come from the OS.

Non-static ("instance") variables should be saved in the instanceState; that's what it's for. See posts like this that sum it up, or most basic Android tutorials that discuss the application lifecycle.

Pretender answered 7/11, 2011 at 3:38 Comment(4)
onSaveInstanceState(...) is not called when I rotate the emulator. And onPause() does not accept any Bundle. Where can I save the instanceState?Cosset
@user639616 Are you sure? It should be, because the activity is destroyed and recreated.Pretender
I overrided onSaveInstanceState(Bundle savedInstanceState) and log some message. But I cannot see the log message.Cosset
I know the reason why I cannot see my log message in onSaveInstanceState(...). It is because the tag` parameter in Log.i(tag, msg)` is too long. Thank you very much for your reply.Cosset
S
0

Each time you rotate screen activity will be recreated -- This is concept of android.

But in your case when activity recreated static value will be retained.. while non static will be reinitialized... So you are getting n=1 always...

If you really want to retain that non static value then go Shared Preferences. In this you can retain all values you need until user clears data....

else simply make non static to static which will solve your probably I guess

Soak answered 7/11, 2011 at 3:49 Comment(0)
A
0

It's very simple: you can override the method onConfigurationChanged() in your code.

public void onConfigurationChanged(Configuration newConfig) 
    {
        super.onConfigurationChanged(newConfig);

    }

So now your non static variable will not affected, because in this time your Activity is not destroyed and not a new activity starts by onCreate() method.

Armilla answered 7/11, 2011 at 5:9 Comment(2)
Do I still have to set the attribute android:configChanges="keyboardHidden|orientation" in the manifest file?Cosset
it IS required!!! onConfigurationChanged is called ONLY IF you set the attribute android:configChanges !Chacha
A
0

Put this line in your activity inside AndroidManifest.xml file:

android:launchMode="singleInstance"

From Documentation

"singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.

A "singleInstance" activity, on the other hand, permits no other activities to be part of its task. It's the only activity in the task. If it starts another activity, that activity is assigned to a different task — as if FLAG_ACTIVITY_NEW_TASK was in the intent.

Akilahakili answered 3/10, 2017 at 18:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.