77

I have a simple activity that loads a bitmap in onCreate. I find that if I rotate the device I can see from the logs that onCreate called again. In fact, because all instance variables are set to default values again I know that the entire Activity has been re-instantiated.

After rotating 2 times I get an FC because not enough memory can be allocated for the bitmap. (Are all instances of the activty still alive somewhere? Or does the GC not clean up fast enough?)

@Override
public void onCreate(Bundle savedInstanceState) {
    File externalStorageDir = Environment.getExternalStorageDirectory();
    File picturesDir = new File(externalStorageDir, "DCIM/Camera");
    File[] files = picturesDir.listFiles(new FilenameFilter(){
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".jpg");
        }});
    if (files.length > 0) {
        Bitmap bm = BitmapFactory.decodeStream(new FileInputStream(files[0]));
        ImageView view = (ImageView) findViewById(R.id.photo);
        view.setImageBitmap(bm);
    }
}

From all that I read, onCreate should be called once during the lifetime of an application. Am I wrong about this? How can re-orienting the device cause the activity to be recreated?

Synesso
  • 37,610
  • 35
  • 136
  • 207
  • However, note that your app **needs** to be robust enough to handle multiple calls to `onCreate`. Make sure you test scenarios like home button, opening another app, then going back to your app. Repeatedly. In fact, temporarily *removing* the `android:configChanges` from the recommended answer is a good way to test the robustness of your app, as it allows you to simply rotate the phone repeatedly to test that. If your app can't survive dozens of rotations back and forth (with onCreate each time), then it will eventually crash in real-world usage, even with `configChanges`. – ToolmakerSteve Sep 25 '18 at 17:35

13 Answers13

90
android:configChanges="keyboardHidden|orientation|screenSize"

Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must decalare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).

From docs: http://developer.android.com/guide/topics/resources/runtime-changes.html

General Grievance
  • 4,555
  • 31
  • 31
  • 45
achellies
  • 986
  • 1
  • 7
  • 2
  • 5
    I had to use this to cover all bases: `keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize` – dtbarne Feb 28 '14 at 05:46
  • Also see [SAHIL's answer](https://stackoverflow.com/a/16415576/199364) for example of the code you use to handle config change yourself, when using `configChanges`. – ToolmakerSteve Sep 25 '18 at 17:46
64

What happen when orientation changed

Life Cycle of orientation

onPause();
onSaveInstanceState();
onStop();
onDestroy();

onCreate();
onStart();
onResume();

---- app recreated and now is running ---

If you do long operation in onCreate() and want prevent re-create your activity add configChanges attribute in your mainfest

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden|screenSize"
          android:label="@string/app_name">

screenSize if you targeting api >= 13

Mina Fawzy
  • 20,852
  • 17
  • 133
  • 156
  • onSaveInstanceState(); method called before onPause() or after onPause() method???? – Manoj Behera May 10 '17 at 05:42
  • onSaveInstanceState called after onPause – Mina Fawzy May 10 '17 at 08:17
  • when is `onConfigurationChanged` called in this lifecycle? – Amrut Bidri Feb 08 '18 at 13:57
  • @AmrutBidri `onConfigurationChanged` is only called when `configChanges` attribute is set. – Simp Slayer May 19 '18 at 14:22
  • @SirBarksalot Okay let's assume `configChanges` is set. When is `onConfigurationChanged` called in this lifecycle? – AdamInTheOculus Jul 13 '18 at 03:21
  • 1
    @AdamInTheOculus - When `configChanges` is set, `onConfigurationChanged` is the **only** call that occurs during a configuration change e.g. on orientation; it happens *instead of* the "orientation lifecycle" shown above. – ToolmakerSteve Sep 25 '18 at 17:49
  • Some device configurations can change during runtime (such as screen orientation, keyboard availability, and when the user enables multi-window mode). When such a change occurs, Android restarts the running Activity ( onDestroy() is called, followed by onCreate()). The restart behavior is designed to help your application adapt to new configurations by automatically reloading your application with alternative resources that match the new device configuration. – Atul Feb 25 '19 at 06:03
  • The method call hierarchy was exactly what I was looking for. However, you should not do this. Better use a ViewModel instead. – Shivam Jha Sep 17 '19 at 10:01
59

Activity is recreated after each rotation by default. You can override this behaviour with configChanges attribute of the activity tag in AndroidManifest. For further details and different options, see http://developer.android.com/guide/topics/resources/runtime-changes.html

Ash
  • 1,701
  • 13
  • 18
28

Actvity Lifecycle when you rotate screen

onPause
onSaveInstanceState
onStop
onDestroy

onCreate
onStart
onRestoreInstanceState
onResume
Linh
  • 57,942
  • 23
  • 262
  • 279
13

If you want to prevent FC from not enough memory, you need to deallocate resources in onStop() or onPause(). this allows you to use fresh memory in onCreate().

This is an alternate solution to preventing the recreation of the activity by using

android:configChanges="keyboardHidden|orientation"

As sometimes your activity's layout is different in portrait and landscape (layout, layout-land). preventing recreate on orientation change will prevent your activity from using the other orientation's layout.

Paul Chu
  • 1,249
  • 3
  • 19
  • 27
josephus
  • 8,284
  • 1
  • 37
  • 57
  • 1
    This actually seems to be the best and most right answer. Instead of preventing a re-layout on orientation change (which is actually a thing you would most likely want to happen in most scenarios) you should definitely release bitmaps on stop and rebuild the on create or try to get them in a Bundle and reuse them – Daniel W. Oct 19 '16 at 12:45
  • Or see [SAHIL's answer](https://stackoverflow.com/a/16415576/199364) for example of the code you use to handle config change yourself, when using `configChanges`. – ToolmakerSteve Sep 25 '18 at 17:46
12

On Create method will call everytime when you do orientation, to avoid this you have to use

//Define Below in you Manifest file.
           <activity
                  android:name="com.ecordia.activities.evidence.MediaAttachmentView"
                  android:configChanges="keyboardHidden|orientation|screenSize"
            </activity>

//Define Below in your activity. 

         @Override
            public void onConfigurationChanged(Configuration newConfig) {

              super.onConfigurationChanged(newConfig);

              if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                  //your code
              } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            //your code

              }
            }

It will works like a charm!!

SAHIL
  • 431
  • 6
  • 18
11

Yes, activity's onCreate() is called everytime when the orientation changes but you can avoid the re-creation of Activity by adding configChanges attribute of Activity in your AndroidManifest file in the activity tag.

android:configChanges="keyboardHidden|orientation"
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
8

Manifest XML activity Tag:

android:configChanges="keyboardHidden|orientation"‍‍‍


@Override
public void onConfigurationChanged(Configuration newConfig) {
    // TODO Auto-generated method stub
    super.onConfigurationChanged(newConfig);
}

Use the above code to perform changes related to orientation in your Activity Java Code

Cheers!!!

Max Base
  • 639
  • 1
  • 7
  • 15
Himanshu Virmani
  • 2,450
  • 1
  • 24
  • 34
  • Perfect! The addition of the line android:configChanges="keyboardHidden|orientation"‍‍‍ into the tag in AndroidManifest.xml solves the problem of onCreate() being called EVERY time there is a configuration change (i.e. when screen orientation changes from Portrait to Landscape and vice versa). This line has to be added in AndroidManifest.xml for every activity where you DON'T want onCreate() called whenever there is a screen orientation change. Another way is using ViewModel here--> https://developer.android.com/topic/libraries/architecture/viewmodel – ONE Jan 17 '22 at 20:15
7

One of the most common and suggested “solutions” to dealing with orientation changes is to not deal with them. You can do this by setting the android:configChanges flag on your Activity in AndroidManifest.xml as shown below:

<activity
    android:name=".MyActivity"
    android:label="@string/title_my_activity"
    android:configChanges="orientation|screenSize|keyboardHidden" />

This is NOT the correct way to deal with orientation changes.

CORRECT way is to implement the onSaveInstanceState method (this could be in your Activity, Fragment or both) and place the values you need to save in the Bundle argument that gets passed to the method.

It is nicely described here: http://code.hootsuite.com/orientation-changes-on-android/

While it may seem a bit tedious to implement, handling orientation changes properly provides you with several benefits: you will be able to easily use alternate layouts in portrait and landscape orientations, and you will be able to handle many exceptional states such as low memory situations and interruptions from incoming phone calls without any extra code.

Andrius Darulis
  • 386
  • 2
  • 12
3

While the Manifest way may work, there is a better and proper solution for these types of problems. The ViewModel class. You should have a look here: https://developer.android.com/topic/libraries/architecture/viewmodel

Basically, you extend the ViewModel class and define all the data members in it which we want to be unchanged over re creation of the activity (in this case orientation change). And provide relevant methods to access those from the Activity class. So when the Activity is re created, the ViewModel object is still there, and so are our data!

Shivam Jha
  • 182
  • 3
  • 17
2

Kindly see my way of doing it:-

http://animeshrivastava.blogspot.in/2017/08/activity-lifecycle-oncreate-beating_3.html

snippet is:-

@Override
protected void onSaveInstanceState(Bundle b) {
    super.onSaveInstanceState(b);
    String str="Screen Change="+String.valueOf(screenChange)+"....";
    Toast.makeText(ctx,str+"You are changing orientation...",Toast.LENGTH_SHORT).show();
    screenChange=true;
}

@Override
public void onCreate(Bundle b) {
    super.onCreate(b);
    ctx=getApplicationContext();
    if(!screenChange) {
         String str="Screen Change="+String.valueOf(screenChange);
         // ...
    }
}
Max Base
  • 639
  • 1
  • 7
  • 15
  • 3
    A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – NobodyNada Aug 03 '17 at 17:17
  • 2
    Additionally, if you're affiliated with the content you're linking to (this looks like it's your blog), you *must* explicitly disclose that: say something like "take a look at this article *that I wrote*" or similar. – ArtOfCode Aug 03 '17 at 17:19
-2

I had the same problem, in which my onCreate is called multiple times when the screen orientation is changed. My problem got solved when i add android:configChanges="orientation|keyboardHidden|screenSize" in the activity tag in manifest

Milan Joseph
  • 118
  • 10
-3

I had the same problem and I did some workaround

Define didLoad boolean variable with false value

private boolean didLoad = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    if (!this.didLoad){
        // Your code...
        this.didLoad = true;
    }
Abdullah Dahmash
  • 525
  • 1
  • 6
  • 12