Best practice: AsyncTask during orientation change
Do NOT use android:configChanges
to address this issue. This is very bad practice.
Do NOT use Activity#onRetainNonConfigurationInstance()
either. This is less modular and not well-suited for Fragment
-based applications.
You can read my article describing how to handle configuration changes using retained Fragment
s. It solves the problem of retaining an AsyncTask
across a rotation change nicely. You basically need to host your AsyncTask
inside a Fragment
, call setRetainInstance(true)
on the Fragment
, and report the AsyncTask
's progress/results back to it's Activity
through the retained Fragment
.
How to handle a running AsyncTask during orientation/configuration change?
According to this page : http://developer.android.com/guide/topics/manifest/activity-element.html#config, if your application targets API level 13 or higher, you should use android:configChanges="orientation|screenSize"
to catch the screen rotation into the onConfigurationChanged()
method.
By doing this, the onPause
and onResume
methods are not called, so your TextView will keep its value. And in my mind, it won't stop the running AsyncTask. If it does, try to recall it in the onConfigurationChanged
method.
Handle orientation change with running AsyncTask
Here are my tips:
Do not use
android:configChanges
to address this issue.Do not use
Activity#onRetainNonConfigurationInstance()
to address it either (as this approach is deprecated).Instead, use a retained worker
Fragment
. I've recently posted an article describing how to handle configuration changes using retainedFragment
s. It solves the problem of retaining anAsyncTask
across a rotation change nicely. You basically need to host yourAsyncTask
inside aFragment
, callsetRetainInstance(true)
on theFragment
, and report theAsyncTask
's progress/results back to it'sActivity
through the retainedFragment
.
How to handle an AsyncTask during Screen Rotation?
My first suggestion would be to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my <activity>
tag in the AndroidManifest.xml, and been just fine.
android:configChanges="keyboardHidden|orientation"
It looks weird, but what it does it hand off to your onConfigurationChanged()
method, if you don't supply one it just does nothing other than re-measure the layout, which seems to be a perfectly adequate way of handling the rotate most of the time.
Best practice to handle orientation change: Android
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 Service
s. 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)
- https://github.com/square/retrofit
- Annotation library to make REST very easy. Works with Robospice.
Volley (Networking data & Images)
- https://android.googlesource.com/platform/frameworks/volley
- https://developers.google.com/events/io/sessions/325304728
- This is the networking code that runs the Google Play Store
- Fast, reliable
- Handles most caching for you with some sensible defaults
- very easy to use
- built specifically for very fast image, json, etc loading
- Handles all threading for you.
Picasso (images)
- https://github.com/square/picasso
- Http library for loading images
- fast
- very easy to use
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
Android Fragments. Retaining an AsyncTask during screen rotation or configuration change
Fragments can actually make this a lot easier. Just use the method Fragment.setRetainInstance(boolean) to have your fragment instance retained across configuration changes. Note that this is the recommended replacement for Activity.onRetainnonConfigurationInstance() in the docs.
If for some reason you really don't want to use a retained fragment, there are other approaches you can take. Note that each fragment has a unique identifier returned by Fragment.getId(). You can also find out if a fragment is being torn down for a config change through Fragment.getActivity().isChangingConfigurations(). So, at the point where you would decide to stop your AsyncTask (in onStop() or onDestroy() most likely), you could for example check if the configuration is changing and if so stick it in a static SparseArray under the fragment's identifier, and then in your onCreate() or onStart() look to see if you have an AsyncTask in the sparse array available.
Handle screen orientation changes when there are AsyncTasks running
I had a similar problem to your and worked around it by implementing the AsyncTask
as part of a class which inherits from Application
class. An Application
class is available all the life time of the application So you don't have to worry about your AsyncTask
getting interrupted unless the whole application will be killed.
To get notified when the task has finished the Activity
has to implement a interface which it uses to register itself to the Application
class.
When your application is destroyed because of the screen rotation you can unregister your Activity
from the Application
class and re-register it when it is recreated. If the task finishes between destruction and recreation the result of the operation can be stored in the Application
class meanwhile so the Activity
can check whether the task is still running or whether the result is already available when it is recreated.
Another advantage is that you have direct access to the applications context because the Application
class is a sub class of the Context
class.
Handle orientation change with running AsyncTask
Here are my tips:
Do not use
android:configChanges
to address this issue.Do not use
Activity#onRetainNonConfigurationInstance()
to address it either (as this approach is deprecated).Instead, use a retained worker
Fragment
. I've recently posted an article describing how to handle configuration changes using retainedFragment
s. It solves the problem of retaining anAsyncTask
across a rotation change nicely. You basically need to host yourAsyncTask
inside aFragment
, callsetRetainInstance(true)
on theFragment
, and report theAsyncTask
's progress/results back to it'sActivity
through the retainedFragment
.
How prevent rotation until AsyncTask is not ended
Its not possible to pause screen rotation. You can only stop it entirely using configChanges in your activity manifest entry (but that is bad practice). What you should do is to put your async task in retained fragment. Until recently you could use Activity.getLastNonConfigurationInstance and Activity.onRetainNonConfigurationInstance to keep reference to AsyncTask between Activity being destroyed and recreated but now its deprecated. But you can still use it.
read here for more information: http://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance()
Also:
if I try to rotate the device during AsincTask the App crashes
this actually should not happen, it is possible that you keep reference to your Activity in AsyncTask and use it after it is destroyed. This is called reference leak. To avoid it keep reference to your Activity in WeakReference, also if your AsyncTask is an inner class, then make it static. If it is possible, destroy your asynctask in Activity.onDestroy - by cancelling it, in async task check if it is cancelled and stop processing. If you use it to download things then consider retained fragment or IntentService.
Related Topics
Failed to Resolve: Com.Google.Firebase:Firebase-Core:9.0.0
How to Get the Height and Width of the Android Navigation Bar Programmatically
How to Build an Executable for Android Shell
Mapview in a Fragment (Honeycomb)
Recyclerview Header and Footer
Start an Activity with a Parameter
Could Not Find Com.Android.Tools.Build:Gradle:3.0.0-Alpha1 in Circle Ci
Huawei, Logcat Not Showing the Log for My App
How to Find the Data Usage on a Per-Application Basis on Android
How to Determine If a Firebase User Is Signed in Using Facebook Authentication
How to Disable Action Bar Permanently
Passing Arraylist Through Intent
What Exactly Does the Post Method Do
Android P - 'Sqlite: No Such Table Error' After Copying Database from Assets
How to Increase Storage for Android Emulator? (Install_Failed_Insufficient_Storage)