Rotation and the Activity Lifecycle
Let's get back to the bug you found at the end of Chapter 2.Run GeoQuiz, press the Next button to reveal the second question, and then rotate the device. (For the emulator, press Control+F12/Ctrl+F12 to rotate.)
After rotating, GeoQuiz will display the first question again.Check LogCat to see what has happened.
Figure 3.10 QuizActivity1 is dead. Long live QuizActivity!
When you rotated the device, the instance of QuizActivity that you were looking at was destroyed, and a new one was created.Rotate the device again to witness another round of destruction and rebirth.
This is the source of your bug.Each time a new QuizActivity is created, mCurrentIndex is initialized to 0, and the user starts over at the first question.You will fix this bug in a moment. First, let's take a closer look at why this happens.
Device configurations and alternative resources
Rotating the device changes the device configuration.The device configuration is a set of characteristics that describe the current state of an individual device.The characteristics that make up the configuration include screen orientation, screen density, screen size, keyboard type, dock mode, language, and more.
Typically, applications provide alternative resources to match different device configurations.You saw an example of this when you added multiple arrow icons to your project for different screen densities.
Screen density is a fixed component of the device configuration; it cannot change at runtime.On the other hand, some components, like screen orientation, can change at runtime.
When a runtime configuration change occurs, there may be resources that are a better match for the new configuration.To see this in action, let's create an alternative resource for Android to find and use when the device's screen orientation changes to landscape.
Creating a landscape layout
First, minimize LogCat. (If you accidentally close LogCat instead, you can always re-open it from Window → Show View...)
Next, in the package explorer, right-click the res directory and create a new folder.Name this folder layout-land.
Figure 3.11 Creating a new folder
Copy the activity_quiz.xml file from res/layout/ to res/layout-land/.You now have a landscape layout and a default layout.Keep the filename the same. The two layout files must have the same filename so that they can be referenced with the same resource ID.
The -land suffix is another example of a configuration qualifier. Configuration qualifiers on res subdirectories are how Android identifies which resources best match the current device configuration.You can find the list of configuration qualifiers that Android recognizes and the pieces of the device configuration that they refer to at http://developer.android.com/guide/topics/resources/providing-resources.html.
You will also get more practice working with configuration qualifiers in Chapter 15.
When the device is in landscape orientation, Android will find and use resources in the res/layout-land directory. Otherwise, it will stick with the default in res/layout/.
Let's make some changes to the landscape layout so that it is different from the default.Figure 3.12 shows the changes that you are going to make.
Figure 3.12 An alternative landscape layout
The FrameLayout will replace the LinearLayout.FrameLayout is the simplest ViewGroup and does not arrange its children in any particular manner.In this layout, child views will be arranged according to their android:layout_gravity attributes.
The TextView, LinearLayout, and Button need android:layout_gravity attributes.The Button children of the LinearLayout will stay exactly the same.
Open layout-land/activity_quiz.xml and make the necessary changes using Figure 3.12.You can use Listing 3.4 to check your work.
Listing 3.4 Tweaking the landscape layout (layout-land/activity_quiz.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" ><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/question_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:padding="24dp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|center_horizontal" android:orientation="horizontal" > ... </LinearLayout> <Button android:id="@+id/next_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:text="@string/next_button" android:drawableRight="@drawable/arrow_right" android:drawablePadding="4dp" /> </LinearLayout></FrameLayout>
Run GeoQuiz again. Rotate the device to landscape to see the new layout.Of course, this is not just a new layout; it is a new QuizActivity as well.
Figure 3.13 QuizActivity in landscape orientation
Rotate back to portrait to see the default layout and yet another new QuizActivity.
Android does the work of determining the best resource for you, but it has to create a new activity from scratch to do it.For a QuizActivity to display a different layout, setContentView(R.layout.activity_quiz) must be called again.And this will not happen unless QuizActivity.onCreate(...) is called again.Thus, Android destroys the current QuizActivity on rotation and starts fresh to ensure that it has the resources that best match the new configuration.
Note that Android destroys the current activity and creates a new one whenever any runtime configuration change occurs.A change in keyboard availability or language could also occur at runtime, but a change in screen orientation is the runtime change that occurs most frequently.