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?
wannik
  • 12,212
  • 11
  • 46
  • 58

6 Answers6

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.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 1
    +1; interesting. I'd never even noticed it was called twice (or if it should matter if it is). – Dave Newton Nov 07 '11 at 04:12
  • +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. – Pedantic Nov 07 '11 at 05:29
  • 3
    I had to use this to cover all bases: `keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize` – dtbarne Feb 28 '14 at 05:47
  • android:configChanges="keyboard|keyboardHidden|orientation|screenSize" I've added. thanks. – iroiroys Jun 18 '15 at 04:58
  • Not only for emulator, its also behaving the same on real device, as well as, configChanges not working out for me :( – Narendra Singh Aug 07 '15 at 11:45
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.

Dhanuka
  • 2,826
  • 5
  • 27
  • 38
Aakash
  • 386
  • 2
  • 15
  • I overrided `onSaveInstanceState(Bundle savedInstanceState)` but it was not called when I rotated my emulator. – wannik Nov 07 '11 at 03:49
  • you may not have properly ovverided the method, it is called just before onPause(). – Aakash Nov 07 '11 at 03:53
  • @Override protected void onSaveInstanceState(Bundle bundle1){ super.onSaveInstanceState(bundle1); Log.i(tag,"inside onSaveInstanceState"); bundle1.putInt("variable n",n); bundle1.putInt("sn",sn); } – Aakash Nov 07 '11 at 03:55
  • 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. – wannik Nov 07 '11 at 04:06
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.

Community
  • 1
  • 1
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • `onSaveInstanceState(...)` is not called when I rotate the emulator. And `onPause()` does not accept any `Bundle`. Where can I save the `instanceState`? – wannik Nov 07 '11 at 03:45
  • @user639616 Are you sure? It should be, because the activity is destroyed and recreated. – Dave Newton Nov 07 '11 at 03:51
  • I overrided `onSaveInstanceState(Bundle savedInstanceState)` and log some message. But I cannot see the log message. – wannik Nov 07 '11 at 03:55
  • 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. – wannik Nov 07 '11 at 04:05
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.

Darush
  • 11,403
  • 9
  • 62
  • 60
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

Dhanuka
  • 2,826
  • 5
  • 27
  • 38
shanmugamgsn
  • 820
  • 5
  • 16
  • 27
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.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
Hemant Menaria
  • 701
  • 1
  • 7
  • 17
  • Do I still have to set the attribute `android:configChanges="keyboardHidden|orientation"` in the manifest file? – wannik Nov 07 '11 at 05:12
  • it IS required!!! onConfigurationChanged is called ONLY IF you set the attribute android:configChanges ! – Massimo Jun 18 '15 at 12:40