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.
Related
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.
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 app (a SyncAdapter) I include many ContentProviders for use by other apps and was wondering whether it is appropriate to attempt to share a single SQLiteOpenHelper instance between them all to use? If so, how?
If that's not appropriate, is it considered correct to (as examples seem to indicate) repeat instantiation of the SQLiteOpenHelper within each ContentProvider's onCreate method; seems like there should be a better way!
Is there sufficient information in the Manifest for the Operating System to instantiate ContentProviders without creating their containing Application first? If so, then I can not hold a static SQLiteOpenHelper in a class that extends Application for retrieval by ContentProviders.
Help!
The answer was to merge my ContentProviders into a single ContentProvider that is wired-up to handle my various URIs/tables; here's an example from Google themselves. This way you can instantiate your SQLiteOpenHelper and set it to a field for your overridden methods to use, again, see the example. By the way, another good (in the interests of best practice) pattern I picked up from that code is to: override applyBatch to wrap everything it does in a transaction. Thereafter use it and only it (via. ContentProviderOperations) whenever you want to do any persistence; if you do this you can omit transactions from your actual overridden update, delete and insert methods - because you'll not be using them directly! The latter appeals to me as it simplifies my insert, update and delete methods and ensures that a whole sequence of related changes can be rolled back easily if an Exception is thrown.
The Android Dev Guide says
Content providers are also useful for
reading and writing data that is
private to your application and not
shared.
Generally, Content Providers are used for providing data to different applications or sharing data among them. I was wondering if there is any use to having private providers and not wanting to share it. Are there any benefits provided that a direct access to DB or file system don't provide?
Thanks,
Rajath
It automatically schedules all your server-side and synchronization DB access in a background thread. However, in your application frontend, the Content Resolver/Provider will normally execute queries/transactions from the UI thread by default. You must perform all transactions asynchronously (i.e. using a CursorLoader) to ensure that your application runs smoothly on the UI side
It localizes re-entrant DB access from the any threads that access through ContentProvider, so that all locking can happen entirely in your ContentProvider override calls, rather than keeping track of it in a DB layer, a service, and a UI layer.
As part of the above, it also provides a nice singleton interface to your data -- If you have ten Activity classes in your app, you just go through ContentResolver static calls from each one, versus needing to deal with opening/closing a SQLiteDatabase in each activity as you jump from one activity to another in your app.
ContentProvider is tied very tightly to the SyncAdapter model -- Meaning it's pretty much the only way to go if you want to keep your database in sync with a server-hosted database out on the net. (your app mirrors a REST api type of situation)
It ties into ContentResolver's ContentObserver interface -- This is an interface where (among many other useful things) a view can register as observing a specific set of data (through the Cursor to that data). Then, if you drive a change into the ContentProvider, the CP can notify the CR, which can in turn notify any relevant cursors, which in turn will requery and cause the view to update. This is much cleaner than having to manually keep track of your views so you can invalidate and redraw them.
As for re-entrant locking of the DB, it doesn't do it completely, but it helps -- your ContentProvider class implements four simple functions (CRUD interface) and, if you choose to override it, a fifth, batchAdd() -- This localizes your locking. The bone simple answer is to simply tag all four/five of those function declarations "synchronized" at the function level and you're done. Much cleaner than trying to figure out locking out from 20 places that access your DB in 5 different Activites.
For example,a multiprocess application use scenario(like: music play service usually run in a remote process), between the two process that in one application share database should use private ContentProvider.
I have a simple approach question about Android design.
I envision a scenario where I provide a service and an activity. Both the service and the activity need to read/write to the same data. The basic idea is a live playlist: the service that is playing the list "pops" a song from the list when it's done playing, but the the app can also edit the list by adding or deleting songs.
I considered using a ContentProvider for the actual playlist, thinking it would be simple, but all ContentProvider examples I can find on the internet seem morbidly overcomplicated or involve solely SQLite.
Another approach would be to keep a simple file in my resources, and access that from both the service and the app.
Which approach seems to be better here? If I should indeed use a ContentProvider, can someone please direct me to the simplest possible implementation, preferably not involving SQLite? From my prior looks, ContentProvider seems overcomplicated for my simple purpose.
Thanks for any opinions!
-Chase
A ContentProvider may persist the data it's entrusted with however it likes. Typically, that means SQLite, because the mapping to the ContentProvider interface is intuitive.
However, as long as your ContentProvider implements the insert(), update(), delete() and query() operations, (or implements as much as the app that uses the provider needs to have implemented to do it's job) you can persist the data that goes in and out using whatever mechanism you like. Feel free to store it in a SQLite database, a file, or whatever.
Just keep in mind that your ContentProvider may be subject to being killed and restarted, maybe even being garbage collected and re-constructed later, so you need to use something that's robust against the class going away and being reinitialized.
In your case, you probably don't care about persisting across reboots (who cares about the playing music list being there after you reboot) so some sort of list in a static variable ought to be sufficient.