Best practice to handle orientation change: Android

11,840

Solution 1

Some summaries

There are several methods mentioned above that are good practices but I thought I might sum them up with short explanations. Below are some of the most popular libraries being used currently for http networking, asynchronous work / threading, and caching.

My current project (just preferences)

I personally am currently using Otto, Loaders, Volley, Ormlite, and a network stack based on Apache and Services. I do hope to replace, the network stack at some point with either Volley, Retrofit, and maybe eventually Robospice.

I personally very much like Otto and Volley


RoboSpice (Modular)

  • https://github.com/octo-online/robospice
  • http://www.youtube.com/watch?v=ONaD1mB8r-A
  • a plugin / modular approach to long-running tasks
  • this is like the "swiss-army-knife" of libraries, but you need to know what each tool does.
  • Handles REST calls
  • persists data through orientation and other changes
  • can handle disk and memory caching )
  • works with various HTTP libraries and persistence libraries (Gson, Jackson, Spring, OkHttp, and many of the below libraries)
  • beta for Ormlite support, I think

Retrofit (REST)

Volley (Networking data & Images)

Picasso (images)

Loaders (Android)

  • well supported
  • persist through orientation change and save/load of fragment state
  • can be difficult to get right
  • no caching

AsyncTask (Android)

  • simple way for background work from the UI thread
  • must be canceled and be careful about tasks that return after an activity or fragment is torn down.

Otto (event bus)

  • https://github.com/square/otto
  • Event bus that makes a-sync work between components and fragments easy
  • Very powerful @Produce ability retains the last event and can produce it on demand for any new interested subscribers to the bus

Headless Fragments (?)

  • I personally have never seen this used other than Vogella's tutorials, so I'm not sure on this one.

Service (Android)

  • The old school way
  • ultimate control, you must do everything yourself
  • usually used with Appache or HURL client and
  • pass Parcels around via Intents

Solution 2

Why don't you try Loaders, in particular AsyncTaskLoader? They are available for pre-Honeycomb through Support Library and perfectly match Activity/Fragment lifecycle. Here is the official summary:

  • They are available to every Activity and Fragment.
  • They provide asynchronous loading of data.
  • They monitor the source of their data and deliver new results when the content changes.
  • They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.

Solution 3

We are actually using RoboSpice library. It runs on a Service with only providing RequestListeners objects.

The problem with your first approach (Keeping references between the AsyncTask) is that you can probably generate memory leaks because when your AsyncTasks holds your Activities references, they will be not garbage collected. Keep an eye on this just profiling your application checking Heap Size rotating the same Activity over and over again. Your heap should grow in the normal parameters (There is a moment when your objects that must be garbage collected lives at the same time with new objects) but when GC runs your RAM allocation should fall to the same size that you've allocated at the beginning.

So if I have to recommend something will be the next thing:

Activity managing API Calls and Flows (With RoboSpice, letting de UI rotate) Simple screens inside Fragments using retainInstance in true. This let to you pass your DTOs directly to your fragments, and you have to only manage the state at the top level Activity.

Solution 4

If handling asyncTask is your main concern i.e not willing to download data each time orientation is changed then you may try like this --

(1) Initialize any value before on create like this ..

Boolean android_hacker = false;

(2) Now when you are done with downloading data on AsyncTask class then set that value to true

android_hacker = true;

Here maintain all data utilizing model and Array adapter class

(3) Now each time orientation is changed then check like this

if( android_hacker = true ){

// Use your saved instance ..

}else{

// Download data as it is yet not downloaded ..

}

Hope it helps ..

Solution 5

There are many ways you can try beside the AsyncTask. And if you try to find a best practice, AsyncTask isn't a good option. This answer explains why you should not use AsyncTask. And they recommend you using a better way which can deal with long running task, RoboSpice.
I have already used this library and I think it is worthy to try: respect activities lifecycles (orientation change), no memory leaks, supports multi-threading, caches results... It can plug and unplug long request task by using cache (but it can't work well for a non-cache request).

But I recommend a good way comes from Google: IntentService and BroadcastReceiver. You will registered and unregistered broadcast during orientation change to receive the data result. All background task will work in IntentService and notify whatever you want to activity by BroadcastReceiver. There are a lots of example that you can try. Something like this: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/

Update:

Hi R4j, the point is my application is quiet complex. And I've to make number of parallel network calls. Your approach with IntentService is good but isn't suitable for complex scenarios

I don't think this is a problem. You can do anything with the IntentService, even the complicated tasks. If you want parallel tasks, you may consider a Service with multithreading in it and communicate with activity by Intent. Sending intent between Service and activity is safe and flexible, that is Android way.
And if you want to cache (by file download, stream, by database..) RoboSpice is a best choice for you

Share:
11,840
Gaurav Arora
Author by

Gaurav Arora

Speaks Android & React Native. LinkedIn: https://www.linkedin.com/in/gauravsapiens Medium: https://medium.com/@gauravsapiens

Updated on July 13, 2022

Comments

  • Gaurav Arora
    Gaurav Arora almost 2 years

    I was going through various practices to handle orientation change with threads and AsyncTask. I came across following solutions:

    1. Attach-detach model : Attaching and detaching activity to threads and AsyncTask while preserving their instance. (Source: 1, 2)

    2. Headless fragment way : Using a non-UI/headless fragment to do all the thread related operations and retaining its instance on configuration change. (Source: 1, 2)

    Are there any other approaches to handle this scenario? What is the recommended practice? I'm asking this because I couldn't find a generic solution anywhere in the Android docs.