Rotational Forces, Part Two

A few weeks back, I wrote about how rotations, including sliding out the keyboard on the G1, affect your Android application. Ed Burnette chimed in with a couple of other points in a blog comment, so I wanted to expand upon what he presented there.

The original post focused on the fact that a rotation, by default, will destroy and recreate your activity, no different than if the activity were reclaimed due to low memory space or other conditions. Hence, in theory, whatever logic you wrote to handle being destroyed to release memory would also cover you for a rotation. Usually, this involves onSaveInstanceState(), so you can persist your current state and get it back in onCreate() or onRestoreInstanceState().

Today, we’ll cover a second approach — onRetainNonConfigurationInstance() — in an adapted excerpt from Version 1.4 of The Busy Coder’s Guide to Android Development.

The problem with onSaveInstanceState() is that you are limited to a Bundle. That’s because this callback is also used in cases where your whole process might be terminated (e.g., low memory), so the data to be saved has to be something that can be serialized and has no dependencies upon your running process.

For some activities, that limitation is not a problem. For others, though, it is more annoying. Take an online chat, for example. You have no means of storing a socket in a Bundle, so by default, you will have to drop your connection to the chat server and re-establish it. That not only may be a performance hit, but it might also affect the chat itself, such as you appearing in the chat logs as disconnecting and reconnecting.

One way to get past this is to use onRetainNonConfigurationInstance() instead of onSaveInstanceState() for “light” changes like a rotation. Your activity’s onRetainNonConfigurationInstance() callback can return an Object, which you can retrieve later via getLastNonConfigurationInstance(). The Object can be just about anything you want – typically, it will be some kind of “context” object holding activity state, such as running threads, open sockets, and the like. Your activity’s onCreate() can call getLastNonConfigurationInstance() – if you get a non-null response, you now have your sockets and threads and whatnot. The biggest limitation is that you do not want to put in the saved context anything that might reference a resource that will get swapped out, such as a Drawable loaded from a resource.

Let’s look at an example. Below is a layout for a simple UI with two buttons:

[sourcecode language=’xml’]

  • falstaff

    Hello,

    I use this method to store a network connection (as you supposed to do so, and also the official docs does). This works fine for orientation changes. But when i press the Home button while my activity is running (onStop is then beeing called, but not onRetainNonConfigurationInstance or onDestroy), and restart it by clicking on the icon, the Activity object seems to be a complete new object and the method getLastNonConfigurationInstance() return null. The second is logic for me, because onRetainNonConfigurationInstance was not called. But because I have a complete new instance now, a new connection to the server is established. But the old connection object seems to be held somewhere too, but I cant get this connection again… Any idea?

    In my opinon either the methods onRetainNonConfigurationInstance and onDestroy should be called when I press the home button, or the same activity should be started when I start the application again. This way I have a new connection each time I restart the activity from the icon….

    Thanks for any hint how to solve this problem!

    bye
    falstaff

  • Pingback: туроператор по израилю()

  • Pingback: Best 10 Hosting Wordpress Themes()

  • Pingback: WordPress business themes 2013()

  • Pingback: web hosting reviews 2012()

  • Pingback: Wordpress Themes for Photographers 2013()

  • Pingback: campshedding increasingly bullhoof()

  • Pingback: accessorily almira astrologistic()

  • Pingback: b i t q u i l l » Hello Android()