Since Honeycomb and the v4 Compatibility Library it is possible to use AsyncTaskLoader. From what I understand, the AsyncTaskLoader can survive through config changes like screen flips.
Is it recommended to use AsyncTaskLoader instead of AsyncTask? Does LoaderManager get in the picture too?
But I haven't found any good example(s) about how to correctly use the AsyncTaskLoader. The docs also provide no examples. Can anyone provide some good examples.
You can have a look at the compatibility library's source code to get more info. What a FragmentActivity does is:
keep a list of LoaderManager's
make sure they don't get destroyed when you flip your phone (or another configuration change occurs) by saving instances using onRetainNonConfigurationInstance()
kick the right loader when you call initLoader() in your Activity
You need to use the LoaderManager to interface with the loaders, and provide the needed callbacks to create your loader(s) and populate your views with the data they return.
Generally it should be easier than managing AsyncTask's yourself. However, AsyncTaskLoader is not exactly well documented, so you should study the example in the docs and/or model your code after CursorLoader.
Comparing AsyncTaskLoader vs. AsyncTask, as you may know, when you rotate your device screen, it may destroy and re-create your activity. To make it clear. let's imagine rotating your device while networking transaction is going on:
AsyncTask will be re-executed as a background thread again, and the previous background thread processing will just be redundant and zombie.
AsyncTaskLoader will just be re-used basing on Loader ID that was registered in Loader Manager before, so re-executing network transaction will be avoided.
In summary, AsyncTaskLoader prevents duplication of background threads and eliminates duplication of zombie activities.
AsyncTaskLoader performs the same function as the AsyncTask, but a bit better. It can handle Activity configuration changes more easily, and it behaves within the life cycles of Fragments and Activities. The nice thing is that the AsyncTaskLoader can be used in any situation that the AsyncTask is being used. Anytime data needs to be loaded into memory for the Activity/Fragment to handle, The AsyncTaskLoader can do the job better.
There are a few issues with using AsyncTasks, though:
Configuration changes can mess things up
Pausing an activity doesn’t pause the AsyncTask
A fair amount of boilerplate code (which means more possible errors)
AsyncTaskLoader doc
Some differences other than described in other answers:
When using AsyncTaskLoader over AsyncTask:
AsyncTaskLoader gives us liberty to load old cached data until new data is returned by forceLoad()
We can set delays to AsyncTaskLoader by setUpdateThrottle() which can prevent consecutive updates to client (Activity/Fragment)
AsyncTaskLoader can be shared to multiple fragments if they have common parent activity and if it was started from getActivity().getSupportLoaderManager()
AsyncTaskLoader is destroyed by LoaderManger when its linked activity is no more available. while we need to manually destroy AsyncTasks if its caller activity destroys. This saves our time from writing all the clearing stuff. AsyncTaskLoader plays well with their respective lifecycles.
So, AsyncTaskLoader is way better than AsyncTask.
Related
I am currently studying about Loaders and about how they could overcome changes such as screen orientation during application lifecycle, and so far, from what I have read, AsyncTaskLoader does the same job as AsyncTask and even better. Therefore, should not AsyncTask be considered obsolete or does it provide the developers with some hidden advantages?
I am currently studying about Loaders and about how they could overcome changes such as screen orientation during application lifecycle
The Architecture Components' support for view-models and LiveData is Google's current direction for addressing the problems that loaders tried to address.
AsyncTaskLoader does the same job as AsyncTask and even better
Note that AsyncTaskLoader uses an AsyncTask.
should not AsyncTask be considered obsolete
Yes, insofar as we have other patterns and libraries to use (e.g., RxJava, LiveData). That being said, AsyncTask, used correctly, is an OK option. The challenge is in using it correctly (e.g., from a retained fragment, with care to avoid interacting with the hosting activity on a background thread).
does it provide the developers with some hidden advantages?
Your argument seems to be "an ocean liner has more features than does a rowboat, so shouldn't we consider rowboats to be obsolete?". Ocean liners have their costs, and ocean liners cannot do everything that a rowboat can (e.g., travel in shallow water, be towed behind a truck).
Loaders were designed — to the extent that they ever had a "design" — to:
load data in the background, typically via an AsyncTask
retain that data across configuration changes
automatically deliver updates when the requested data happens to change
Not everything needs that. For example, the loader pattern targets read operations (where we actually "load" data), but it does not really help with write operations (where we are changing the data). Yet we still want to do write operations asynchronously and find out about the results even if we undergo a configuration change. You can squeeze write operations into loaders, but it is not a natural fit. Using an AsyncTask or something else, instead of a loader, would be more natural.
Think this way,
The AsyncTaskLoader can be used at any place where the AsyncTask is.
The main advantage is the ability to persist between the lifecycles.
If you use an AsyncTask and call a Network Operations to get some data from the Internet and the User rotates the phone, your AsyncTask will have to start the task again to grab the data, and this could be potentially dangerous to your application because you could have a memory leak.
So, in any case, Loaders are an evolution of the AsyncTask, they are basically improved AsyncTasks.
I believe that the AsyncTask is still alive because when you are performing some simple task in the Background Thread you can do this more simply using an AsyncTask with an anonymous inner class, and deliver the results right away to the UI Thread.
Cannot understand when I need to use Loader and when AsyncTaskLoader? I read docs by these class but I understood it badly. As I understood Loader allows to do a background work so it must be launched in non-GUI thread, it isn't? Why does AsyncTaskLoader do all same? I'm confused already.
Please, someone explain me more details.
All of the Loader methods are called on the main thread - Loader does not do any work on a background thread. This allows you to use whatever loading mechanism you want - be it a separate thread, callbacks to another component, or anything else.
AsyncTaskLoader extends Loader and adds loadInBackground(), a method specifically called on a background thread. It is simply a convenience class for the simple case.
In either case, the real role of Loaders is to make loading data lifecycle aware as explained in this blog post - Loaders (and hence, AsyncTaskLoaders) survive configuration changes such as screen rotations. The blog contains a number of examples of AsyncTaskLoader, using an AsyncTaskLoader with an observer of changes, and a Loader which gets data from another data source using callbacks.
I was going through various practices to handle orientation change with threads and AsyncTask. I came across following solutions:
Attach-detach model : Attaching and detaching activity to threads and AsyncTask while preserving their instance. (Source: 1, 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.
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)
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
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.
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.
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 ..
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
You can try with the following approaches:
1) If your application does not explicitly require any orientation changes, just disable orientation changes at the beginning of app execution, thereby you would be avoiding any crashes or related problems with respect to orientation changes.
This you can do using the following line in the outermost layout of your layout xml file:
android:orientation="vertical"
(for setting vertical orientation)
2) You can set or preserve previous orientation values at the beginning of your thread execution using Asynctask, as follows (syntax example only):
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
and
getResources().getConfiguration().orientation
Look at LoaderCustomSupport (Use AsyncTaskLoader) and FragmentRetainInstanceSupport (Use Thread, almost equivalent to AsyncTask)
Both examples have the following similarities.
Both do not block UI thread when loading data
The data fetching thread is not destroyed when user performs configuration change like screen rotation.
When data fetching thread finished fetching data, it can update to the correct Fragment UI
However, there are differences.
AsyncTaskLoader
Seems like there is no easy way to update intermediate progress to a progress bar dialog
AsyncTask
Not sure on this. But Android documentation seems to recommend AsyncTaskLoader for async data loading and updating final result to UI?
Is there any guideline, or checklist to look at, to make a decision on whether to choose AsyncTaskLoader or AsyncTask, to do a time-consuming loading task and update the result to Fragment's UI?
your question made me interested and tried sometimes to look into the differences. Here i am writing my observations.
For the premature termination the asynchronous task using AsyncTask will continue running in its thread. The processing of the results can soon lead to unrequested results while AsyncTaskLoader handle the premature termination of the activity
AsyncTaskLoader handles activity configuration changes (IE when the user rotates the screen).
AsyncTaskLoader is intended load data for DataAdapters so for this purpose it is best to use AsyncTaskLoader But if you need to change UI (specially fragments) after task completion it is better to use AsyncTask as you can't change fragments in onLoadFinished of AsynTaskLoader.
So to me the usage depends on your task. and if the above 3 points doesnt bother you then the performance is same ( haven't found any documents though , but in this case asynctaskloader is recommended :S)
some related links
AsyncTaskLoader vs AsyncTask
http://andreas-kluck.blogspot.com/2012/02/asynctask-and-asynctaskloader.html
AsyncTaskLoaders, like all Loaders, are intended to solve the rotation problem, which is when an AsyncTask is created on an Activity, then the device is rotated before the task has completed that AsyncTask will be lost with the destruction of the Activity.
It's true that all Loaders currently don't support publishing progress, so if this is a requirement for your situation then you should consider an alternative. If rotation, or any other event that causes the Activity to be destroyed, isn't an issue then just use an AsyncTask, otherwise you might want to use a Service, and register a binder to push progress messages back and forth.
Service and Binder messages are kind of a pain though, in my opinion. I find a much easier solution is to use LocalBroadcastManager to send progress broadcasts from an IntentService (or AsyncTaskLoader) and have a BroadcastReceiver in the Activity receive the broadcast and display the progress.
If I need to asynchronously load some data via HTTP (or whatever) in order to update the UI, I have a few options when writing an Android application (among many others that I'm sure I missed):
Use a regular thread and a handler to update the UI.
AsyncTask
Use and IntentService, and use either a callback or broadcast the results via an Intent.
Using Loaders.
From what I understand, an IntentService is not tied to an Activity's lifecycle, so any changes to orientation, etc, will not impact the retrieval of data. Where this is not the case for an AsyncTask or thread fired off within an Activity.
The reason for the question, is that I just recently read about Loaders, and am confused as to their application. They seem to be more closely tied to a data source, where if the data source changes, then "transparently" everything is handled appropriately. Loaders also appear to be tolerant to configuration/orientation changes (I believe).
I've been currently using an IntentService to make RESTful service calls, and broadcasting the results to be received by appropriate Activities.
I'm assuming I could write an HTTP based Loader, but I'm not sure if this is the best use of this mechanism.
What are the advantages/disadvantages to using one of the async data loading methods over any other?
All of these mechanisms are simply options. There's no such thing as a one size fits all tool and so all of these different methods of completing the same task is a way to cover as many use cases as possible.
Ultimately, it's up to you to decide which method makes more sense for your scenario. But for a sort of generic explanation of what you should use...
Regular thread and a handler - Why when there are other, simpler, options?
AsyncTask - Since an AsyncTask will almost always depend on an Activity, use this when you need to load data asynchronously and you are 100% certain of how long it may take. Example: Executing an SQLite query.
IntentService/Service - Services are not bound to an Activity like an AsyncTask is, therefore, they are perfect for scenarios in which you may not know how long it will take to complete. Example: Downloading data from a web API and updating a database.
Loaders - Loaders are aimed at simplifying the process of loading data and populating it into UI. The nature of Loaders sort of assumes that the data you will be loading will be presented to the user as a list of some sort. Example: Downloading data and populating it into a ListView