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
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.
I would like to have all my Activities (7 to 10 different screens) submit data to a "controller" (sorry if I'm miss using the term).
Inside said controller data would either be uploaded or saved to data for uploading when no internet.
The controller would do checks and processing such as:
Checking for valid session.
Attach other needed credentials before
upload etc.
Session/User data would be stored in a Shared Preferences file the controller has reference to.
My goal is to have Activities do nothing more than collect the data and call the appropriate method (with a data object) asynchronously. The controller would know how to process the data for uploading or saving in the database.
Would placing these methods in an extension of Application be a bad idea?
It was mentioned that depending on application size this is feasable, but there could be better solutions.
Depending on the size of your project, that would be a suitable idea. However, there are some other ways you should know before choosing the method you're actually implementing:
Using a ContentProvider for your data, an AccountAuthenticator and then sync to the server using an SyncAdapter. Advantages are a good abstraction, independence from activities and many built-in features (for example: Android executes your code without a big battery life impact). However, implementing all the stuff is quite much work at first. If you don't want to use the ContentProvider, the same technique works with a stub implementation as well, the same goes for the AccountAuthenticator.
Using a Service, probably IntentService, for your uploading needs. Advantage is that the Service has an independent lifecicle and thus is not directly related to your Activity; a Service can get restarted if it has been killed by the system. Still more work than just using some static methods.
Using a static method as you're proposing it (in your case, the Application object; not completely static, but compareable). Quite easy to implement, probably the best way if there are similar tasks in multiple activities; your AsyncTasks can send their result directly to the activitiy that started it. However not suitable for long-running tasks.
Implementing within the Activity; If code is only used once; listed for completeness only, not for your case. Basically the same as using a static method.
These are the ones that popped into my mind, there might be some others, too. Feel free to add/suggest additonal ones.
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.
Background
I've heard that there are some new solutions for loading data in the background which are more recommended than AsyncTask (like loaders).
The problem
AsyncTasks are great and easy to use. However, it has some limitations:
The class itself has to be modified since it's limited by the number of pending tasks (about 256 or so). Of course, in a listView's adapter, I always cancel a task if it's not needed(for example when I need to update a view that was used for a different item).
I also have to cancel them all (or handle in a different way) when the activity/fragment is being re-created.
Because of 1&2, I need to manage them and have a reference to all of them
AsyncTask uses a queue of tasks, and sometimes I need to use a stack instead, so I had to create my own class of AsyncTask that uses a stack instead.
The question
Are there alternatives for AsyncTask?
I know this was asked in some posts before (like here), but I was thinking if there is a new general way to load data in the background which replaces the asyncTask.
About Loaders, I think the idea is that they are used for databases and contentProviders, but can they also be used for loading (for example) data from the Internet (like images files) ?
There is also a nice sample made by google (here, called "bitmapFun"), which according to what I see uses AsyncTask (and even extend it, maybe because of the same reasons I've mentionsed) . But maybe I'm missing there something too?
Maybe you should consider reviewing your approach, the need you have for performing several updates depending on the view and cancel all the pending tasks from the previous views gives the impression that you are performing the load of data individually for every view that needs to be created.
In a list view with a list adapter, the usual approach is to load a portion of the data (either as list of ValueObject or as Cursor from multiple database rows) paginated on demand or in one goal, not item by item. So if you wish to update the next page, you basically perform one single operation, either using AsyncTask or Loaders to fetch the new items to the model then making it available for the UI to display them. This way, you will be applying MVC, and you won't have several pending tasks to cancel and control, and your structure would be more solid and easier to manage.
About the alternatives, If you're dealing with database, the most straightforward way is to use the CursorLoader, i.e. the loaders instead of AsyncTask, but if you're dealing with data that comes from the network or filesystem, you're kinda free to choose from the variety of other options available. AsyncTask is much more simpler to use, mostly recommended for simple things or one shot queries. But you can also use Loaders for such tasks as well, see AsyncTaskLoader.
Yes.
Loaders are managed AsyncTasks. If you are not using a Loader, you are probably missing the management that they require.
AsyncTasks (and Loaders) are a pretty bad way to get stuff that is off the device. To get data from a remote server look into using an IntentService. See: https://www.youtube.com/watch?v=xHXn3Kg2IQE
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask. See the http://developer.android.com/reference/android/os/AsyncTask.html for more info.
An alternative to asynctask is robospice.https://github.com/octo-online/robospice.
You can get started with robopice here. https://github.com/octo-online/robospice/wiki/Starter-Guide.
A sample of robospice at https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result.
Some of the features of robospice.
1.executes asynchronously (in a background AndroidService) network requests (ex: REST requests using Spring Android).
2.is strongly typed ! You make your requests using POJOs and you get POJOs as request results.
3.enforce no constraints neither on POJOs used for requests nor on Activity classes you use in your projects.
4.caches results (in Json with both Jackson and Gson, or Xml, or flat text files, or binary files, even using ORM Lite).
5.notifies your activities (or any other context) of the result of the network request if and only if they are still alive
6.no memory leak at all, like Android Loaders, unlike Android AsyncTasks notifies your activities on their UI Thread.
7.uses a simple but robust exception handling model.
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