6

I have used both approaches:

  1. Let the activity be destroyed on rotation
  2. Don't let the activity be destroyed on rotation

My approach almost everytime is to catch the rotation event and if needed call the setContentView and add some components again. If not, just let it rotate and the layouts are designed to adapt.

So far I only have seen advantages on letting it be destroyed on screens with very complex construction that are very dynamic, and whenever I rotate and not destroy show some flickering when re-building the screen.

The overhead of having to pass the state with onSaveInstance, onRestoreInstace is sometimes very error prone, and somehow time consuming.

Am I missing something?

UPDATE:

I'm not doing any kind of if "Orientation.XPTO == ..." on my code. This is the logic of each of the 2 approaches (the code is reused):

When destroying

onCreate -> DrawUI() setContentView and add views -> fill() add content

When not destroyed:

onCreate -> DrawUI() setContentView and add views -> fill() add content
onRotation -> DrawUI() setContentView and add views -> fill() add content

When calling setContentView after rotation it will pick the right layout for the device orientation (Check this answer by Google's Reto Meier https://stackoverflow.com/a/456918/327011 )

And the DrawUI and fill would have to have the logic for both the portrait and landscape layouts as the activity can be created on each of the two orientations to begin with.

Community
  • 1
  • 1
neteinstein
  • 17,529
  • 11
  • 93
  • 123
  • 1
    "If restarting your activity requires that you recover large sets of data, re-establish a network connection, or perform other intensive operations, then a full restart due to a configuration change might be a slow user experience. Also, it might not be possible for you to completely restore your activity state with the `Bundle` that the system saves for you with the `onSaveInstanceState()` callback—it is not designed to carry large objects (such as bitmaps) and the data within it must be serialized then deserialized, which can consume a lot of memory and make the configuration change slow." – jnthnjns Nov 30 '12 at 15:25

5 Answers5

11

Am I missing something?

Yes. You are assuming that your alternative is somehow less error prone.

By not going through the destroy-and-recreate cycle, you have to ensure that you are handling changing every resource for every possible configuration change.

Don't let the activity be destroyed on rotation

Unless you are using android:screenOrientation to force your activity into a single orientation (e.g., landscape), you cannot only handle rotation-related configuration changes. You need to handle all configuration changes. Otherwise, as soon as the user drops their device into a dock, removes it from a dock, changes language from Settings, attaches or detaches a keyboard, changes the global font scaling, etc., your app will break.

This, in turn, means that on every configuration change, you need to:

  • update your UI for your potentially new string resources
  • adjust or reload your layouts (and by "adjust" that includes changing any drawables, animations, menus, etc.)
  • anything else tied to your resources (e.g., array lists in your PreferenceFragment)

The problem is that you are going to forget something. For example, you will miss changing a string associated with an action bar item, so now most of your UI is in Spanish and that action bar item is in English. The sorts of things you are going to forget will be less obvious (how often do you test your Spanish translation?).

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
3

Your activity is destroyed to give you the opportunity to reconfigure yourself for the new orientation.

From the developer.android.com:

When the screen changes orientation, the system destroys and recreates the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout).

For example, in landscape mode you may require a completely different layout, or may want to load in graphics that would not appear stretched. The best way of doing this is allowing the activity to be created again, which will allow the linking to the layout file to change to a more orientation-friendly layout.

See http://developer.android.com/training/basics/activity-lifecycle/recreating.html for more info and how to deal with the orientation change

If you want to disable the recreation you can add

android:configChanges="orientation"

to your Activity element in AndroidManifest.xml. This way your Activity will not be reloaded.

onSaveInstance and onRestoreInstace should only be used for passing through session information, for example the current text in a TextField, and nothing generic that can just be loaded in again after onCreate.

biddulph.r
  • 5,226
  • 3
  • 32
  • 47
  • Yes. But if you use android:configChanges="orientation" you can also setContentView and the layout for that specific orientation will be correctly loaded. So... still not advantage? – neteinstein Nov 30 '12 at 15:29
  • Not an advantage if you have an activity maybe, but for a larger scale activity you will have to make sure the correct resources are loaded in and you could be writing a sea of code to do this. The activity recreation will remove the need for that, and you don't have to worry about dealing with the refresh. – biddulph.r Nov 30 '12 at 16:01
  • Not really if you deal with it from the beginning. Check the updated question. – neteinstein Nov 30 '12 at 16:06
2

If you, restarting the Activity, requires recovering large sets of data, re-establishing a network connection, or perform other intensive operations then using the onSaveInstanceState() could potentially cause your noted symptoms:

  1. A poor user experience (i.e. "show some flickering")
  2. Require consumption of a lot of memory

onSaveInstanceState() callbacks are not designed to carry large objects.

To retain an object during a runtime configuration change:

Override the onRetainNonConfigurationInstance() method to return the object you would like to retain. When your activity is created again, call getLastNonConfigurationInstance() to recover your object.

However:

While you can return any object, you should never pass an object that is tied to the Activity, such as a Drawable, an Adapter, a View or any other object that's associated with a Context. If you do, it will leak all the views and resources of the original activity instance. (Leaking resources means that your application maintains a hold on them and they cannot be garbage-collected, so lots of memory can be lost.)

Source


Unless you are able to pass the Object(s) smoothly I personally think it is more advantageous to handle the configuration change yourself, meaning not to destroy.

If you have a target API of 13 or higher: You must include screenSize in your configChanges. Starting with API 13 the screen size also changes on orientation change and you'll need to account for this. Prior to 13 your Activity would handle this itself.

android:configChanges="orientation|screenSize"
jnthnjns
  • 8,962
  • 4
  • 42
  • 65
0

Some time it is useful when you are using different layouts for (Landscape / Portrait ). and using different type of views for example ListView in portrait and GridView in landscape.

Ali Imran
  • 8,927
  • 3
  • 39
  • 50
  • Yes. But if you use android:configChanges="orientation" you can also setContentView and the layout for that specific orientation will be correctly loaded. So... still not advantage? – neteinstein Nov 30 '12 at 15:30
  • But as i said if you are using different components then you have to first check the origination and then fill the appropriate view just like ListView and GridView. – Ali Imran Nov 30 '12 at 15:36
  • Nop. The code is the same as if the activity is destroyed. Check the updated question. – neteinstein Nov 30 '12 at 16:09
0

I guess you are not considering the standard way of creating the android layouts. Please correct me If I'm wrong. Are you using two res folders with -port,-land separately to tell android system to choose in runtime to load the different assets and layout on the basis of orientation.

This example can give you a clue to manage layouts in different orientations.

Here is the android stanard document. Please check with "land" and "port".

Hope this will help you.

Community
  • 1
  • 1
Ajay Kumar Meher
  • 1,932
  • 16
  • 24
  • To handle a very dynamic layout change I usually push/pop the layouts using fragments. I just have to save the state of the ui(user inputs if any) and fill it after changing the orientations with the required fragment rather allowing it to destroy. In this way it becomes highly manageable. – Ajay Kumar Meher Dec 10 '12 at 13:38
  • "Are you using two res folders with -port,-land separately to tell android system to choose in runtime to load the different assets and layout on the basis of orientation." - Yes – neteinstein Dec 10 '12 at 13:51
  • Did you went through the example that I'hv suggested. – Ajay Kumar Meher Dec 10 '12 at 14:26
  • For any system you have two options to work with any application. "With all time give overhead to the processor by destroy/create everytime or keep in-memmory and use when required(If really very complex)." Choose wisely for your application. First one will drain battery and second one will eat memmory. – Ajay Kumar Meher Dec 10 '12 at 14:30