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.
Related
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.
If I do need it, I'll have to modify about 15 classes (models and model-manager classes), so I really want to know if I need a ContentProvider.
Here's where I am:
Similar to Twitter, I'm getting rows of data from a server, and saving it locally in case the user has no Internet connection. But the ideal way is to always get it from the Server.
I am probably not going to use SimpleCursorAdapter because the rows of data I get from the server includes URLs, which means I have to create a custom adapter to display images.
I need to load data into the ListViews asynchronously because I'm having a ViewPager with 3 Fragments that shows the same data (different filters tho), so, since a ViewPager loads 3 Fragments into memory, it means 3 queries are executing (and that's most likely the cause of non-smooth swiping).
So far, the way I synchronize data between the App and the Server is:
Fragment.onStart() executes an AsyncTask which returns rows of data formatted as JSON data
Said AsycTask.onPostExecute() updates the List<E> and calls Adapter.notifyDataSetChanged()
The issue here is that each time I change tabs, the onStart() is called, ergo the AsyncTask executes causing the UI not being smooth.
Should I change the way I synchronize data with the Server, or should I use ContentProvider?
EDIT: as a head up, the reason I'm asking is that startManagingCursor() method is depracated. It says to use the Loader framework, but it seems it's only available through ContentProvider
You don't need to develop your own provider if you don't intend to
share your data with other applications. However, you do need your own
provider to provide custom search suggestions in your own application.
You also need your own provider if you want to copy and paste complex
data or files from your application to other applications.
from http://developer.android.com/guide/topics/providers/content-providers.html
I wrote a custom CursorLoader based on the SimpleCursorLoader source code that comes within the support library. You can search this site for more information about writing a custom one.
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?).
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.
I'm writing an app that allows people to set alarms for various tasks that they need to do. My current plan is to store all the relevant data into an SQLite database. To that end, I have created a class that extends SQLiteOpenHelper and filled it with methods to handle all the CRUD that I'd expect to have to take in. Knowing that it's generally a bad idea to do all the processing on one thread, I looked up ways to separate the work between threads and found CursorLoader and LoaderManager, which seemed ideal as they were available in the Android Compatibility Library. However, LoaderManager seems to require a ContentProvider going by the tutorial in the documentation, and I haven't really seen a need to do anything with ContentProviders since I wasn't planning on allowing other apps to access the data. Without a ContentProvider, I don't know how I'm supposed to get a Uri for my databases to feed into the CursorLoader. Is there a way for me to keep using my class that extends SQLiteOpenHelper and still implement LoaderManager to allow me to keep all the populating ListFragments with my cursor off of the UI thread?
Is there a way for me to keep using my class that extends SQLiteOpenHelper and still implement LoaderManager to allow me to keep all the populating ListFragments with my cursor off of the UI thread?
You just need a different Loader implementation, one that does not involve a ContentProvider. It just so happens that I wrote one of those.