I am still confused. I have read several tutorials of loaders and asynctask in Android but I can't understand some differences in some cases. For example:
Your app can't continue without the information which is provided by Asynctask or Loader
If you need information from MySQL database, what will be better?
And...What if you need information from SQLite database?
Maybe, you might need data from a url.
Your app can continue without the information which is provided by Asynctask or Loader
If you need information from MySQL database, what will be better?
And...What if you need information from SQLite database?
Maybe, you might need data from a url.
If you consider we must mention more differences or other case, you can write it.
Well, both of them are used to perform asynchronous operations, it doesn't really matter if your app can or can't continue without the information. Even if your app can continue wihtout the data, you still need to process it asynchronously to avoid an ANR message.
One reason to choose a Loader or an AsyncTask would be if you need to get data updates. The advantage of the Loaders is that they keep track of the data you are accessing and deliver new results when the data changes.
Other difference is that with Loaders you don't have to worry about configuration changes (orientation change e.g.). The LoaderManager takes care of that for you. With AsyncTask you need to take care of that yourself.
And there is even an AsyncTaskLoader, that does what AsyncTask does but with the benefits of Loaders.
The advantage of AsyncTask is that is very simple to use. If you don't need to load or monitor data, but just process something in the background. AsyncTask is still a good choice.
Cursors are simply used to reconnect to the last cursor onec it has been interrupted for a reason. They are usually designed to use in fragments or activitys.
Documentation for Loaders:
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.
Asynctask are more likely a wrapper which contains a whole subset of methods to access the mainUI and background thread.
Related
I saw some articles about CursorLoader like this, but I still don't understand the particular purpose of using it.
I developed apps with SQL and cursor retrieving. The point is it was very fast. I queried and parsed cursor with >500 record and 8 columns by a few millisecond. So didn't notice any delay event on old phones. So why do I need to use it?
A CursorLoader is used ostensibly to query a ContentProvider with LoaderManager.LoaderCallbacks<Cursor>.
There are two things that you need to keep in mind for understanding the CursorLoader:
It loads data on a separate thread.
It monitors the underlying data source for updates, re-querying when changes are detected.
Now coming to the LoaderManager. Simply stated, the LoaderManager is responsible for managing one or more Loaders associated with an Activity or Fragment. Each Activity and each Fragment has exactly one LoaderManager instance that is in charge of starting, stopping, retaining, restarting, and destroying its Loaders. These events are sometimes initiated directly by the client, by calling initLoader(), restartLoader(), or destroyLoader(). Just as often, however, these events are triggered by major Activity/Fragment lifecycle events. For example, when an Activity is destroyed, the Activity instructs its LoaderManager to destroy and close its Loaders (as well as any resources associated with them, such as a Cursor).
The LoaderManager does not know how data is loaded, nor does it need to. Rather, the LoaderManager instructs its Loaders when to start/stop/reset their load, retaining their state across configuration changes and providing a simple interface for delivering results back to the client.
So you see, all this is not easily possible when you use a simple AsyncTask and query an SQLite database. This is why the framework provides CursorLoader and LoaderManager:
To perform queries on a separate thread.
To monitor the data source for changes and update the UI.
To integrate easily with the life cycle of Activity and Fragment.
The practical purpose is simply how Android handles UI elements (that is on the main thread). Basically, anything that may be a long running process, run it in a background thread so you don't lockup the main thread. This can't be said enough. After Gingerbread this has been more enforced by Android itself. Check out SQL helper. To get to the point in regards to opening an SQLite connection and its "speed":
Because they can be long-running, be sure that you call getWritableDatabase() or getReadableDatabase() in a background thread, such as with AsyncTask or IntentService.
By using CursorLoader, it makes your life easier if you need ContentResolver and are using SQLite DB. More importantly, it runs on the background. Just because you've never seen the DB lock up doesn't mean it doesn't happen. Better safe than sorry, and the main thread will thank you :)
Use the CursorLoader from Support Library to run asynchronous queries in the background. In this way, you ensure that data loading does not cause “Application Not Responding” messages.
A CursorLoader runs a asynchronous query in the background against a ContentProvider and then it returns the result back to the Activity or the Fragment from where it is called.
The main advantage is that it helps the user to interact with Activity or Fragment while the query is still running in the background.
As I posted here Need SQLite to replace only rows with new information, I need to get information from a webserver and compare it with what I have in my SQLite database. (Android App)
I currently have an AsyncTask implemented that gives me a HashMap.
I was in the process of coding an SQLite database when I came across Loaders.
I am confused about how to do this.
Do I want to use CursorLoader or AsyncTaskLoader in this case? Do I replace the current AsyncTask subclass that I have now?
private class getFleetList extends
AsyncTask<String, Integer, HashMap<String, ArrayList<Vehicle>>> {
#Override
protected HashMap<String, ArrayList<Vehicle>> doInBackground(
String... params) {
//...implemented AsyncTask
}
My current guess is that I will replace my AsyncTask. A tutorial link or something would be very helpful. All tutorials that I have found use broadcast receivers or post to ListViews and that is not what I am doing.
Thanks
An AsyncTask runs code on a non-UI (usually called a "background") thread. An AsyncTask can do anything, but it's a bit fragile because it disappears if the system restarts the Activity that started the AsyncTask. This can happen quite easily, because the system restarts the current Activity if the user rotates the device (unless you trap onSystemConfigurationChanged).
Formally, an AsyncTaskLoader is a Loader that uses AsyncTask to run its code. This means in real terms that an AsyncTaskLoader gets data from somewhere by using a non-UI thread (the AsyncTask part). The loader part just gives you convenience methods for dealing with the process of getting data, which may take a long time. The loader part also lets you track the data and restart the load if the data changes.
Based on what you've said, your current implementation can use either AsyncTask or AsyncTaskLoader. If you need the features of Loader, choose AsyncTaskLoader; otherwise, stick with AsyncTask.
You can't use CursorLoader. Although it's not immediately obvious, you need a content URI to create a CursorLoader, which means you need a content provider. In your situation, there's no obvious advantage in using a CursorLoader. A CursorLoader adds stuff on top of AsyncTaskLoader, such as a built-in ContentObserver that automatically triggers reloads when data for the original CursorLoader query's content URI changes.
Basically, you're just looking at layers of class definition that add functionality for more and more specific situations.
Having said all this, I see that you want to ensure that a web server's database and the device's database are always "in sync". Correct?
You can always tell when a row has changed in a content provider, because you can register a ContentObserver for the provider. When something in an app tries to mutate the data being "observed", you get a callback. The system detects the mutation by comparing the URI passed to the ContentResolver call to the URI you register to observe. Unfortunately, you can't do this for an SQLite database.
If data on the web server changes, you can notify a device using Google Cloud Messaging.
In both cases, you can create a sync adapter to handle the data transfer and synchronization tasks, and run it when the data changes.
The tricky part is deciding how to handle conflicts, but you're only looking for updates and additions (and deletions?).
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.
In my application I need a lot of CRUD stuffs: read records from the local SQLite database, insert objects and updating stuffs. Most of the queries are so simple that they won't block even if run on the UI thread, however in this application I want to adopt the Windows Phone pattern: an out animation started immediatelty and an in animation started when the result is delivered.
I planned to use an AsyncTask for the job, however I noticed that Honeycomb (and the compat package) introduces this new Loader framework. The main advantage seems that data loaded by a Loader survive config changes. The LoaderEx project by Commonsware bridges between SQLite and the framework, but some problems arise.
Resources cleanup: I use a single activity, create the SQLiteOpenHelper in onCreate() and close it onDestroy(). Since the loader manager may still be running, i check it and set a pendingClose flag on my callbacks object, so it will close the cursor and the helper when load finishes. I think not closing the database is not harmful, but SQLite complains if you don't do it, and I don't like error messages :) The point here is that data doesn't survive config changes, so the Loader advantage vanishes
How many loaders should I create? Let's say I have the beloved Customer and Order tables. Loaders are identified by ID's like CUST_L or ORD_L, but every time the user clicks on some summary I want to bring in a screen with the detail. Should I restart a loader with different params, or should I init a new one with a random ID? This may happen dozens of times. Is the Loader framework intended for lots of small running jobs, or just for a few long running tasks?
What's the purpose of using ID's inside the LoaderCallbacks interface? Why not a simple initLoader(params, callback)? I don't think one can reuse some piece of logic inside a callback: eventually he will branch (with if-else or switch on ID) so I don't understand the point of giving an identifier to the callbacks object, instead of a naive approach one-callbacks-per-operation.
I'm asking this because the whole framework seems overengineered to me and without real utility. I don't understand the point of centralizing code with a LoaderManager, and I can't see any new opportunity AsyncTask did not offer.
The only win point is config changes survival, but I can't exploit it because of resources cleanup, and I can't figure out an alternative way to close the SQLiteOpenHelper because (quite obviously) the SQLiteCursorLoader requires it but clean it up is up to the user. So AsyncTask seems the winner choice here, but maybe I'm missing something.
Content providers are much more powerful than "raw-DB" approach. Lots of links on stackoverflow lead to discussions on this.
LoaderManager tries to distinguish loaders by their IDs (what's why signature of initLoader specifies this argument). ID for loader is needed to re-deliver cached result in case if data for loader with specific ID already exists (hence no need to asynchronously re-load it again).
restartLoader call forces LoaderManager to initiate async opertation specified by previously created loader. initLoader attempts to reuse existing loader before creating a new one.
Fragments and Activities have their own LoaderManagers that don't overlap.
My experience shows that even though using Content Providers sounds like overkill to implement, it actually pays off pretty good in the future. Performance hit is insignificant (tried measuring it), UI-Data bindings are added out of the box (because of content observer and CursorLoaders being able to subscribe to Uri notifications), synchronicity implemented by framework via loaders. IMHO, whenever database is needed, using content provider with loaders most of the times is the best solution you can come up with.
Other scenarios that involve using database directly, will force you to implement everything manually.
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