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.
Related
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
For what I understand, the Loader framework is geared towards accessing data stored locally in a ContentProvider / SQLite database. We have the CursorLoader class that handles this use case quite well.
But I wonder if it's practical to use the Loader framework to write classes extending Loader / AsyncTaskLoader to access remote web services (e.g. a REST web service)? I always thought that this framework is a bit too rigid and confusing (lack of proper documentation) for this use case. I prefer handling REST calls in more regular way, using AsyncTasks / Services. But recently I've found some articles that used AsyncTaskLoaders and began to wonder.
So why would anyone use Loaders to access Web Services? The only advantage I see here is that Loaders retain their results automatically. There's no Cursor here to manage afterwards.
Realistically, you probably want to use a networking library like Volley. This has some nice features like request batching and image caching. Nonetheless, for the sake of argument lets compare Service, Loaders and AsyncTask.
Services are the way to go if you want to allow the loading to continue while changing Activities or backgrounding your application. Or, if you want to export your service so multiple applications can use it. Otherwise, use a Loader or AsyncTaskLoader.
Loaders have a few advantages over AsyncTasks.
They are less likely to cause crashes by executing code after the Activity has finished, since they are aware of the android lifecycle.
The design discourages having references to Views or Activities. This reduces the likelihood of forcing the Activity to stay in memory after it has already finished.
Monitor the data source for changes and trigger callbacks when they occur
They have built in caching that can be useful after rotations. For Cursors, the CursorLoader automatically reconnects at the correct position to the last Cursor loaded
However, they also have disadvantages
The API is extremely more cumbersome than AsyncTask. Especially if you care about compatibility with older versions of Android
You are already storing UI state inside onSaveInstanceState(), so using the Loader's causes you to save state in multiple ways. This can be confusing to read and understand. Especially if you end up mixing retained fragments into the mix.
The Loader caches the loaded result, not the UI state that you actually need
I'm assuming you are just reading from web services, not writing. If you are performing updates to a web service and you need to see the service's response, then this changes things. Using an AsyncTask could prevent you from getting the response if the it is received during a rotation.
There are cases where Loader is suitable for webservices: When your server can send push notifications back to client to notify that data is changed.
I need to make a design decision.
From what I read in the android developers site I think I want to implement a Service which launches an AsyncTaskLoader to load data from an OS process in the background.
In the android developers site documentation it says that AsyncTaskLoader can be used in Activities and Fragments, but no mention of Services.
Is it a bad practice to use AsyncTaskLoader in a Service?
If so, how do I collect data from a running OS process in the background? (Note: I need the collection to go on even if the app is closed/destroyed)
Loaders are generally used for UI elements that are created and destroyed relatively often, and need to access the previously queried objects without re-querying every time. A Service won't be destroyed mid load like an Activity or Fragment will, so spawning a new Thread is considered the best practice for loading data in the background in a Service.
Loaders are really for Activities and Fragments, it might make sense to consider an IntentService if you just want a good way to do some work in background threads. Is there something specific that looked useful in AsyncTaskLoader?
Either way you won't be able to keep collecting if your app is destroyed. If your app is destroyed, it's not there to do any work. A Service of some sort is definitely what you want to use to do work in the background though.
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
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.