Check SQLite database for duplicate entries, CursorLoader/Loader/AsyncTaskLoader? Confusion - android

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?).

Related

Should I use a Cursor or a CursorLoader?

I have an android app in which I have a login system and some other stuff that communicate with the server. Sometimes I just get from the web server just a confirmation and sometimes I get a lot of data. So far I was using a simple database. Today I implemented a Content Provider which is working so far. To get data from the ContentProvider I used this Cursor cursor = getContentResolver().query();, but I saw that there is also the option to use a CursorLoader. What is the difference between them ? In my case what should I use ? I also saw that I have to implement it in every class the cursorLoader, can't I make a single class for it and call it when it's needed ?
As the documentation states,
CursorLoader implements the Loader protocol in a standard way for
querying cursors, building on AsyncTaskLoader to perform the cursor
query on a background thread so that it does not block the
application's UI.
This is the biggest advantage of using Loaders, i.e. it is asynchronous. Some of the other important advantages are also mentioned here.
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.
If you use the default cursors by querying the content provider directly then you need to handle closing them, and as you said you have huge data, you'd have to run the query code on a different thread. For all these purposes using CursorLoaders is much simpler and efficient. For code on how to use one, check this out.
As to your second question,
I also saw that I have to implement it in every class the
cursorLoader, can't I make a single class for it and call it when it's
needed ?
You can very well make a Base class that will be implementing the loader callbacks and then you can inherit that base class from all the classes that need to use the CursorLoaders.

What's practical purpose of cursorLoader?

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.

When should I use Loaders? and when asynctask? (Android)

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.

Safely add/remove ListView item from different thread

After filling a ListView from local SQLite I want to fetch data over the network from a remote Database in order to retrieve new Data, and show it in the ListView so that the local SQLite Database is just a fallback method in case of no internet.
I was using a different Thread to insert the network-fetched data into the SQLite and then re-fill the ListView list.
Naturally, the app crashes because at some point the second Thread is removing every item on the list (to add new ones) and at the time, the UI Thread is trying to access an index who's been deleted by the secondary thread.
Since this is for academical purpose, the idea is not using external/custom libraries, so what'd be a good approach that doesn't include custom libraries?
Wrap the database in a content provider. Not difficult to do, since you already have the database. Instead of writing your own Thread, use an IntentService to fetch the network data and write it into the content provider.
In your Activity, use a CursorLoader to load the data from the content provider in the background. CursorLoader includes an implementation of onDataSetChanged(), so every time the content provider is updated, the Cursor will be reloaded. Every time the Cursor reloads, swap the new Cursor into the CursorAdapter that backs your ListView.
To communicate between the IntentService and your Activity, do two things:
Send a local broadcast Intent (using LocalBroadcastManager) from the IntentService to the
Activity when the network download completes. If your Activity is in the foreground, it
will get the broadcast immediately, and you can fire off CursorLoader for the first time.
Also post a notification from the IntentService. In this notification, include a content
Intent. If your Activity is in the background and the IntentService completes, the user
sees the notification. He or she can then click the notification to go back to your
Activity. You can fire off CursorLoader if you need to, or what until CursorLoader restarts automatically.
Your issue points out the desirability of rethinking app structure when you're programming in Android. Android apps aren't linear; they're more like mega-objects that interact with each other according to their current state. For this reason, you should avoid writing your entire app in one Activity, or writing it from the top down.
Also, there's hardly ever a reason to create a new Thread() on your own. Android offers plenty of classes that handle asynchronous processing for you. If you find yourself coding a Thread() or run(), be wary.
Only update the ListView on the main application thread. For example, instead of a Thread, use an AsyncTask, where you do your disk and network I/O in doInBackground() and update the ListView in onPostExecute().
Because the data shown in ListView is shared, you have to protect it via synchronization. You should write the code synchronized (data) {// data operation} in different thread in case of crash

Android Async Data Loading Methods

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

Categories

Resources