Repository Pattern is defined by Hieatt and Rob Mee as design pattern that mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
Basically it abstracts one or more I/O devices (cloud, disk, data base, etc) into a common collection-like interface where you can read, write, seek and delete data.
On Fernando Cejas's Android Clean Architecture, all data needed for the application comes from this layer through a repository implementation (the interface is in the domain layer) that uses a Repository Pattern with a strategy that, through a factory, picks different data sources depending on certain conditions.
However, as pointed out by professor Douglas Schmidt at Coursera course, content provider manages and mediates access to a central repository of data to one or more applications
In the book Programming Android, content providers are used as a Facade for a RESTful Web Service. This approach was initially presented by
Virgil Dobjanschi during Google I/O 2010.
Thus, instead of using content providers to access the local SQLite database, why not using it as the repository pattern itself?
Let's try to compare the Repository Pattern definition from the book "Patterns of Enterprise Application Architecture" by Martin Fowler
(with Dave Rice, Matthew Foemmel, Edward Hieatt, Robert Mee, and Randy Stafford) with what we know about ContentProviders.
The book states:
A Repository Mediates between the domain and data mapping layers using
a collection-like interface for accessing domain objects.
The important bit is accessing domain objects. So at first glance it seems that the repository pattern is only meant for accessing (querying) data. With a ContentProvider, however, you not only can access (read) data but also insert, update or remove data.
However, the book says:
Objects can be added to and removed from the Repository, as they can
from a simple collection of objects, and the mapping code encapsulated
by the Repository will carry out the appropriate operations behind the
scenes.
So, yes Repository and ContentProvider seem to offer the same operations (very high level point of view) although the book explicitly states simple collection of objects which is not true for ContentProvider as it requires android specific ContentValues and Cursor from Client (who uses a certain ContentProvider) to interact with.
Also, the book mentions domain objects and data mapping layers:
A Repository Mediates between the domain and data mapping layers
and
Under the covers, Repository combines Metadata Mapping (329) with a Query Object (316)
Metadata Mapping holds details of object-relational mapping in metadata.
Metadata Mapping basically means i.e. how to map a SQL column to a java class field.
As already mentioned ContentProvider returns a Cursor object from a query() operation. From my point of view a Cursor is not a domain object. Moreover, mapping from cursor to domain object must be done by the client (who uses a ContentProvider). So data mapping is completely missing in ContentProvider from my point of view. Furthermore, the client may have to use a ContentResolver too to get the domain object (data). In my opinion this API is a clear contradiction with the definition from the book:
Repository also supports the objective of achieving a clean separation
and one-way dependency between the domain and data mapping layers
Next let's focus on the core idea of the Repository pattern:
In a large system with many domain object types and many possible
queries, Repository reduces the amount of code needed to deal with all
the querying that goes on. Repository promotes the Specification
pattern (in the form of the criteria object in the examples here),
which encapsulates the query to be performed in a pure object-oriented
way. Therefore, all the code for setting up a query object in specific
cases can be removed. Clients need never think in SQL and can write
code purely in terms of objects.
ContentProvider requires a URI (string). So it's not really a "object-oriented way". Also a ContentProvider may need a projection and a where-clause.
So one could argue that a URI string is some kind of encapsulation as the client can use this string instead of writing specific SQL code for instance:
With a Repository, client code constructs the criteria and then passes
them to the Repository, asking it to select those of its objects that
match. From the client code's perspective, there's no notion of query
"execution"; rather there's the selection of appropriate objects
through the "satisfaction" of the query's specification.
ContentProvider using a URI (string) doesn't seem to contradict with that definition, but still misses the emphasized object-oriented way. Also strings are not reusable criteria objects that can be reused in a general way to compose criteria specification to "reduces the amount of code needed to deal with all the querying that goes on."
For example, to find person objects by name we first create a criteria
object, setting each individual criterion like so:
criteria.equals(Person.LAST_NAME, "Fowler"), and
criteria.like(Person.FIRST_NAME, "M"). Then we invoke
repository.matching(criteria) to return a list of domain objects
representing people with the last name Fowler and a first name
starting with M.
As you have already said (in your question) Repository is also useful to hide different data sources as an implementation detail the client doesn't know about.
This is true for ContentProviders and specified in the book:
The object source for the Repository may not be a relational database
at all, which is fine as Repository lends itself quite readily to the
replacement of the data-mapping component via specialized strategy
objects. For this reason it can be especially useful in systems with
multiple database schemas or sources for domain objects, as well as
during testing when use of exclusively in-memory objects is desirable
for speed.
and
Because Repository's interface shields the domain layer from awareness
of the data source, we can refactor the implementation of the querying
code inside the Repository without changing any calls from clients.
Indeed, the domain code needn't care about the source or destination
of domain objects.
So to conclude: Some definitions from Martin Fowler et al. book match the API of a ContentProvider (if you ignore the fact that the book emphasized object-oriented):
Hides the fact that a repository / ContentProvider has different data sources
Client never has to write a query in a datasource specific DSL like SQL. That is true for ContentProvider if we consider URI as not datasource specific.
Both, Repository and ContentProvider, have the same "high level" set of operations: read, insert, update and remove data (if you ignore the fact that Fowler talks a lot about object orientated and collection of objects whereas ContentProvider uses Cursor and ContentValues)
However, ContentProvider really misses some key points of the repository pattern as described in the book:
Since ContentProvider uses URI (also string for the where clause) a client can't reuse Matching Criteria objects. That is an important thing to note. The book clearly says that the repository pattern is useful "In a large system with many domain object types and many possible queries, Repository reduces the amount of code needed to deal with all the querying that goes on". Unfortunately, ContentProvider doesn't have Criteria objects like criteria.equals(Person.LAST_NAME, "Fowler") that can be reused and used to compose matching criterias (since you have to use strings).
ContentProvider miss entirely data mapping as it returns a Cursor. This is very bad because a client (who uses a ContentProvider to access data) has to do the mapping of Cursor to domain object. Furthermore, that means that client has knowledge of repository internals like name of columns. "Repository can be a good mechanism for improving readability and clarity in code that uses querying extensively." That certainly is not true for ContentProviders.
So no, a ContentProvider is not a implementation of the Repository pattern as defined in the Book "Patterns of Enterprise Application Architecture" because it misses at least two essential things I have pointed out above.
Also, please note that as the name of the book already suggests, the repository pattern is meant to be used for Enterprise Application where you do a lot of queries.
Android developers tend to use the term "Repository pattern" but don't actually mean the "original" pattern described by Fowler et al. (high reusability of Criterias for queries) but rather mean a interface to hide the underlying data source (SQL, Cloud, whatever) and domain object mapping.
More here: http://hannesdorfmann.com/android/evolution-of-the-repository-pattern
Short answer: a Contentprovider is a datasource and not a repository.
The purpose of SQL-Database/Android-Contentproviders/Repositories is to create/read/update/delete/find data
Repositories usually operate on high level busines specific java classes (like Customer, Order, Product, ....)
while SQL-Database and Android-Contentproviders operate on low level table, rows and colums as a datasource.
Because a SQL-Database is not a repository so an Android-Contentprovider is not a repository, too.
But you can implement a repository by using an underlying Contentprovider
I'll mention Dianne Hackborn (from Android Framework team) to give my opinion.
ContentProvider
Finally, the ContentProvider is a fairly specialized facility for publishing data from an app to other places. People generally think of them as an abstraction on a database, because there is a lot of API and support built in to them for that common case... but from the system design perspective, that isn't their point.
What these are to the system is an entry-point into an app for publishing named data items, identified by a URI scheme. Thus an app can decide how it wants to map the data it contains to a URI namespace, handing out those URIs to other entities which can in turn use them to access the data. There are a few particular things this allows the system to do in managing an app:
• Handing out a URI doesn't require the app remain running, so these can go all over the place with the owning app being dead. Only at the point where someone tells the system, "hey give me the data for this URI" does it need to make sure the app owning that data is running, so it can ask the app to retrieve and return the data.
• These URIs also provide an important fine-grained security model. For example, an application can place the URI for an image it has on the clipboard, but leave its content provider locked up so nobody can freely access it. When another app pulls that URI off the clipboard, the system can give it a temporary "URI permission grant" so that it is allowed to access the data only behind that URI, but nothing else in the app.
What we don't care about:
It doesn't really matter how you implement the data management behind a content provider; if you don't need structured data in a SQLite database, don't use SQLite. For example, the FileProvider helper class is an easy way to make raw files in your app available through a content provider.
Also, if you are not publishing data from your app for others to use, there is no need to use a content provider at all. It is true, because of the various helpers built around content providers, this can be an easy way to put data in a SQLite database and use it to populate UI elements like a ListView. But if any of this stuff makes what you are trying to do more difficult, then feel free to not use it and instead use a more appropriate data model for your app.
Full text here:
https://plus.google.com/+DianneHackborn/posts/FXCCYxepsDU
Kudos for the question, it's a nice observation :). IMHO, this is not a yes or no question because it is quite general, as most design patterns related topics are. The answer is depending on what context are you taking in account:
If you have an app that relies entirely on the platform, meaning that take into account only the context of the Android ecosystem, then yes, the ContentProvider IS an implementation of the Repository pattern. The argument here it is that the content provider was designed to solve some of the same challenges that the repository patterns aim to solve:
It provides abstraction over data layer, so the code is not necessarily dependent on the storage environment
No direct data access from everywhere. You can put all your SQL queries (or whatever) in a single place. When I first implemented a ContentProvider as a noob, it was like a revelation to me how clean my code can look like and how comfortable I can be doing changes
Centralizes the data and shares it between multiple clients (other apps, a search widget as you already know) and provides mechanism for data security
You can definitely define data related behavior (one way is by using ContentObserver)
It's a pretty good way to force you from the early stages to organize your code with unit testing/ automated testing in mind
If you put all of above side by side with the principles of the repository pattern, there are some serious similarities. Not all of them are satisfied, but the core ideas are the same.
Now, considering an app working on a larger scale in multiple environments (i.e web, mobile, PC) the requirements change completely. It is a bad idea as everyone suggested to rely on the ContentProvider as a design pattern.
It's not necessarily a bad idea in itself, but a design pattern must be implemented so others can understand your code as fast as possible. You see, even here everyone suggested a common use of ContentProvider: as a datasource, or anyhow something platform dependent. So if you force an implementation on top of a component with known purpose, things can become rather unclear. It's much nicer to organize your code in a classical pattern.
tl;dr; If your app is isolated on your Android device you can definitely merge the two concepts. If your app is used on a larger scale, on multiple platforms it's cleaner, to organize your code in a classical manner.
That is an interesting question. I think my first answer will be no, Content Provider is not an implementation of the Repository Pattern.
As you mentioned, the Repository Pattern is meant to separate the business logic (domain) from the data layer. This approach allows you to create unit tests for your business logic (so domain should not depend on Android at all). By using a Content Provider you will need to have some sort of Android objects in your domain.
You could imagine a way to hide the Content Provider logic behind an Interface, but you will loose many of the nice stuff a Content Provider allows you to do.
If you are interested in Android Architecture I would recommend you to have a look at this Github project Android Clean Architecture. You will find a nice way to separate your presentation, domain and data layer, and the communication between the domain and data is done by using a Repository Pattern.
Hope this will help!
IMHO, it's better to consider a Contentprovider as a datasource, although the data can be stored in several ways (SQLite database, files, ...), to keep some independence between the architecture and the Android framework.
A Google repository provide some samples of architecture. One of them contains an example of architecture with a content provider and a repository :
googlesamples/android-architecture/todo-mvp-contentproviders
Selected excerpts :
You could then use content providers to support additional features that are not covered by this sample, providing the following possible benefits:
Allow you to securely share data stored in your app with other apps.
Add support for custom searches in your app.
Develop widgets which access data in your app.
The problem with using ContentProviders as Repository is that you add a dependency in your model to the Android Framework. Using the repository patterns allows you to easily mock, test and replace implementations.
The correct approach would be to hide the ContentProvider under an interface, and have the model accessing the data through this interface. This way, your code is decoupled from the platform.
Basically, the ContentProvider is the I/O source you want to abstract.
Content Provider is a Android component, the smell will not be good if you mix the repository concept with this component, it creates a blocking dependency on your application.
Related
I'm starting to learn Android development, and also have been trying to follow the DDD design patterns. One thing that has me confused is where application logic goes with respect to ContentProviders.
ContentProviders look a lot like repositories to me, but a lot of times I don't want to expose my repositories directly. There may be some additional application logic inside a Service which the repositories/database.
Most of the examples of ContentProviders I find show them accessing the database directly. Is it wrong to have a Service or Application object in between the ContentProviders and database?
For example I'm trying to create a personal finance/budget app (e.g Mint/Quicken etc..). I'm going to have a database of transactions and a corresponding TransactionProvider. In most cases transactions are independent from one another. Yet if two transactions are marked as part of the same "Transfer" there there will be some fields that I will want to keep in sync between the two transactions. If someone changes the category or amount of one transaction, I want to make sure the same values are updated for the transaction for the other account of the transfer.
A ContentProvider can execute arbitrary code on its insert(), update(), delete() and query() methods. They are not necessarily mapped one-to-one with the corresponding database operations, and neither do the structure definitions (i.e. fields) themselves. You could, for example:
Update more than one table when you insert, update or delete.
Keep normalized tables in SQLite, but present a non-normalized interface for querying.
Not store data in a database at all (for example to expose/manipulate the files available in your application's private storage).
&c.
So you can, indeed, include whatever business logic you want in the "backend" of the ContentProvider. In your case that would mean updating associated records to keep them in sync.
Just to clarify, since you're starting Android development, it's not necessary to build a ContentProvider if you just want to store data in SQLite -- you can use SQLiteDatabase directly for that. A ContentProvider is generally to expose your own data to other applications, or for specialized cases such as search suggestions.
From Creating a Content Provider:
Decide if you need a content provider. You need to build a content
provider if you want to provide one or more of the following features:
You want to offer complex data or files to other applications.
You want to allow users to copy complex data from your app into other apps.
You want to provide custom search suggestions using the search framework.
You don't need a provider to use an SQLite database if the use is
entirely within your own application.
If you're building a financial data app, you probably don't need one. Do you want other applications to be able to access that data?
I'm fairly new to Android development, but am having trouble wrapping my head around Content Providers and specifically what the benefits are (if any) to creating one for a single-app, single-DB SQLite data source. I can see that if I want to use a Sync Adapter, I need a Content Provider, but honestly the Sync API is so underwhelming that I don't think there is any advantage over rolling my own remote sync process using REST.
I also see that by implementing a Content Provider over my SQLite DB, I get a guaranteed Android-managed singleton, but I'm using AndroidAnnotations which can do singleton management for me and it doesn't seem from what I've read that it's even necessarily recommended to have a singleton DB helper as long as I manage my open connections properly.
Am I missing something? The Content Provider API seems surprisingly low-level and error-prone for a single DB app. Specifically managing URI mappings "by hand" and introducing that weird abstraction layer seems like it doesn't add much value.
So is there value in Content Providers for local SQLite DB's? And if so, is there some framework out there that will generate my URI mappings for me or is it strictly roll your own?
First, the Sync API does much more than just loading data from your server. It controls batching your sync updates with other applications' syncs across the entire system, ensures connectivity before running, and optimizes for battery life across the entire system (as explained when running Sync Adapters periodically and in the transferring data using sync adapters guide).
Second, using a Content Provider allows you to very easily take advantage of the Loaders framework (available in the Support Library as well) and CursorLoader which allows your UI to automatically update as data changes in the Content Provider. This can vastly reduce the amount of boilerplate required throughout your Activities.
If the boilerplate of the Content Provider itself is an issue, then you can certainly use Annotation frameworks such as ProviGen to automatically generate the vast majority of a Content Provider for you.
There are also some features in Android that can only be done with the help of a Content Provider, including custom search suggestions and sharing app private files to other apps (although the helper FileProvider class that extends ContentProvider is most of what you'd need for that).
UI testing can be made much easier as well as you can use the provided MockContentProvider to mock up specific sets of data without having to change your Activity code (assuming it is only loading data from the Content Provider of course).
I'm having a hard time to optimize backwards compatibility, complexity and best practice for SQLite database handling on Android. I found two not deprecated ways to manage SQLite databases and cursors:
Directly through android.database.sqlite
ContentProvider, CursorLoader and LoaderManager
I'm trying to design the database implementation future proof. This means I would like to implement a best practice promoted by Google. I found a tutorial on implementing ContentProvider and LoaderManager.
If I follow Lars Vogels proposals, my code is blown up with duplications and unnecessary complexity. It does make sense for some tables in my database. But it would make no sense to implement this for a mapping table with three fields (for example). Furthermore I'm having problems with ActionbarSherlock and the Callback Interface of LoaderManager (there's a solution but it would double my data handling classes).
Direct handling of database and cursors via android.database.sqlite is provoking problems with resource management (close your cursors!) and makes me responsible for task handling.
My Questions:
How are you handling SQLite databases on Android?
When do you go the extra mile and implement ContentProvider and LoaderManager?
How do you stay backwards compatible?
My current approach:
I created a class that separates database I/O (via android.database.sqlite) from activities. All methods open and close the cursors they use during their execution (outside of my activities) and return the objects or the data as needed (instead of a cursor). I/O operations are performed in AsyncTasks. This approach seems very deprecated.
I recently had the same plain sqllite / content provider dilemma, and it looks like content provider are the most common approach to solve the problem.
Even if the official doc states that
You don't need to develop your own provider if you don't intend to share your data with other applications
they added the option to have unexported content providers using
android:exported="false"
All the books I read, including Reto Meier's Professional Android Development 4, suggest using content providers.
Moreover, at the cost of a lot of boilerplate code, you can forget about multithreading and open cursor issues.
Anyway, I have to say that the biggest advantage you get from the content provider / cursor loader combo is that your loader is automatically notified whenever the underlying data changes.
If you use plain sqllite you need to implement some way to get the client classes notified whenever the data changes in background. For example, I used broadcasts to notify any activity that the tables where updated inside an intentservice.
Finally, I was a bit disappointed by all the code duplication that you are ranting about, and I decided to write a python script to generate the content provider in my place using just a description of the data model. You probably have to modify the generated class (or better, to extend it), but I think it saves quite a lot of time. You can find it here
Conclusion:
if you want to export your data to other apps (not so common), you need to go for content provider
if you want to observe the data / update the ui because your dataset might be changed in background, content provider + loader is extremely powerful
if you have a preloaded data set, and maybe you update it in the same activity that display the data, or you need to perform simple operations with your tables, maybe a sqllite helper class is just enough
I understand that Content Providers are made to allow publicly sharing data between applications. However, I'm wondering if anyone has thoughts about making a Content Provider to use just within your own app. Would there be any advantages to doing this? Any disadvantages?
In the past I've just implemented the SQliteOpenHelper to access data from my database, but I'm considering creating a Content Provider. I feel like the URI approach to requesting data is clear and concise. On the other hand, will using a Content Provider just for my application be redundant ( since within it I will have a SQliteOpenHelper class ) and more work than I need?
I would argue it is definitely a good idea to use a ContentProvider even if you don't intend to make it public.
It's good practice to provide the extra level of abstraction over your data to make it easier to change internally. What if you decide to change the underlying database structure at a later time? If you use a ContentProvider you can contain all the structural changes within it, where as if you don't use one, you are forced to change all areas of the code that are affected by the structural changes. Besides, it's nice to be able to re-use the same standard API for accessing data rather than littering your code with low-level access to the database.
Also, there is always the chance that you might want to expose your data in the future. If you don't use a ContentProvider up front, it will be much harder to retrofit it in at a later date.
Then, there's the other parts of the Android where ContentProvider's are required/recommended such as when using SyncAdapters and if you want an App Widget that involves data access for instance.
In summary, there is very little overhead involved in writing a ContentProvider up front (once you have learned the API which is a good idea anyway) so it makes sense to do so, even for private data.
If you are not planning to share data, don't think about Content Providers. They are powerful but hard to write and it will be just silly to implement them if you are going to use them internally.
However, I'm wondering if anyone has thoughts about making a Content Provider to use just within your own app.
Of course... for instance, for an old TODO list app I wrote, I had to write a content provider to allow other apps retrieve and access the tasks states. It was part of the requirements, but more than that it made sense and made the app nicer.
Take a look at the MOTODEV Studio for Eclipse. It is a development environment that extends Eclipse. They have a tool where you can automatically generate a content provider for a database. If a content provider makes it easier to access your data and it doesn't have a significant impact on performance go ahead and use it. In most scenarios this will be the case.
In short,Content Providers helps in managing your data effectively. I would suggest to use them for the following reasons.
It acts as an abstraction layer between your UI and database. You can implement data validation in ContentProviders to validate the data entered by the user. It also lets you to modify the structure of the database without touching the UI and other parts.
They play along nicely with other android framework classes like SyncAdapter. For eg., you can automatically refresh a list, when a value in a database changes using ContentProviders along with CursorLoader. Without ContentProviders you have to implement a lot of functionalities like these on your own.
We can safely expose our private data to other apps. Using ContentProviders will allow us to share our data easily and safely with other apps.
So even if you don't need any of these functionalities now, you might need them in future and its good to go the extra mile and implement them right now.
I agree ContentProviders are a little difficult to grasp but they are definitely helpful, even if you want to use them internally for you own app. The best thing about it is that you can customize the contentproviders for suitable URIs.
Here's a scenario where you may have 5 tables in your database, but you need to join a few of them in certain orders before using them. And make a content URI for each of these joins. You could then each use these URIs as a table :)
I suggest you go ahead with Content Provider, you'll be amazed to see how powerful it is.
In my view point, the content-provider comes with plenty of advantages leave alone just sharing data with other apps. If you need to synchronize with the server using a Sync-Adapter, use google cloud messaging, auto update the UI when the underlying data in the DB changes using Loaders, implement search, use widgets... then the content provider is for you.
I prefer you follow the guideline on because one day you may need to implement some of the above features attached to the content-provider
By the way, you can quickly build you database and CP in less than 5 minutes using content provider generator
As said in documentation:
Creating a Content provider
You don't need a provider to use an SQLite database if the use is
entirely within your own application.
So why bother developing this overhead? You want easier and faster development, right? So one layer of abstraction (SQLiteOpenHelper descendent) is enough.
See Occam's Razor
Do not make an entities without very good reason.
Using a Content Provider can help in an additional level of abstraction - Putting it within your own application make add a significant development time to your project. However if you are using it to share data, application settings or configurations across multiple applications then the Content Provider is your choice.
Watch your security levels and I would recommend using SQLcipher to encrypt data-at-reset (DAR) if your Content Provider is writing to SQLite. (I've used a content provider in a few solutions and provided the ability to take a live "snap shot" of the operational values for debugging and testing.)
Do not use content provider if do not wish to share data with other apps. Use simple sqlitedatabase to perform database operations. Be careful while using content providers for storing confidential data because your confidential information may be accessed by other apps
i have done SQLite database programming for Android, but i dont know anything about
Content-Provider except this: "As i have referred Android Developer page , Android SDK explained about "Content-provider" as it is used to store and retrieve data."
But then,
What is the exact difference between "Content-Provider" and "SQLite Database"?
Which is best to store data, when ?
Any example or helps !!
I found one major difference, as follows:
Storing your data in a database is one good way to persist your data, but there's a caveat in Android-databases created in Android are visible only to the application that created them. That is to say, a SQLite database created on Android by one application is usable only by that application, not by other applications.
So, if you need to share data between applications, you need to use the content provider model as recommended in Android. This article presents the basics of content providers and how you can implement one.
I found this article at this link
Really nice information provided.
What is the exact difference between
"Content-Provider" and "SQLite
Database"?
ContentProvider is a facade -- an API you can implement that exposes databases to other processes. It can be implemented in a way where the data is stored in a SQLite database, but it does not have to be.
Which is best to store data, when ?
That is impossible to answer in the abstract. Generally speaking, unless something is requiring you to use a ContentProvider, just use a database.
I have made many good apps with thousands of users using them which simply used SQLite methods. But that was a while ago and I had to manually write lots of code which now can easily be taken care of by ContentProvider. Back then I was not in favour of using Content Providers because it seemed to only add complexity in the code.
However for last couple of years, as Android has evolved, I have moved to ContentProvider as it saves time and allows you do to more. I now use it extensively. Once you have a Content Provider class written, your life becomes much easier. With ContentProvider I can much easily deal with Cursor Loaders, Loader Callbacks and Bulk Inserts for which I had to write everything manually in the past and still it didn't work as efficiently. Especially when updating the list view, which is now automatically updated thanks to just one notifychange() method. This means now I don't have to type my own listeners and manually updating the content in list views and adapters. Plus, I don't need to worry about opening and closing of databases or worry about memory leaks. That's all handled by the Content Provider. The only problem which once in a while I face is that that you cannot do some complex queries in ContentProviders. In this case you can still use raw queries and use the old fashioned manual interaction with sqlite.
If you have previously written your own DbAdapter, Helper and Observer, you can safely carry them on to your new apps without spending time to convert everything to ContentProvider. But based on my experience, I would highly recommend to move to ContentProvider. It'll take some time to get used to it, but once you have got experience with it, you'll stay with it.
UPDATE 2017
I have now switched to Realm, a much better way to use databases on any platform. Spend a few hours learning it, and save countless hours in your app development career.
1. Content Providers are not Thread Safe
By default content providers are not thread safe. If you have multiple threads using a content provider you can see many different exceptions being thrown and other data inconsistencies. The easiest way to fix this is to use the synchronized keyword on each of the public methods exposed by the content provider.
In this way only one thread at a time can access these methods.
2. Play nice when doing lots of writes
I have the need in the new Serval Maps application to import data from binary files into the database used internally by the application. In order to do this and play nice with the rest of the application it is best to:
Spawn a new thread to undertake the import so other threads are not adversely impacted, in particularly the thread in charge of updating the UI; and
Pause briefly at the end of the each import to give other threads which need to use the synchronized methods more of a chance.
3. Content providers force you to think laterally sometimes
The way that content providers in Android work is to provide a layer of abstraction between the rest of your code and the underlying database. This is mainly due to the fact, as far as I can tell, that content providers can access data from places other than databases.
This means that you can’t execute raw SQL queries on the underlying database and you need to specify the various components of a SQL query using variables passed to the various methods such as the query method. If you have a task that doesn’t fit into the way that SQL is handled by a content provider you have two options:
Think laterally about the query, maybe you can get the data that you need by alternative queries and accessing the results from the cursor; and
Use a URI for accessing the data normally and a special URI that is matched to a specific query for those tasks that don’t have alternatives.
Content Providers are used when you want to share your data across applications.
If you have a database attached with an application and you want another application to use some data, you can implement a content provider that exposes the data
The main difference is: when your app needs to share information to another apps, use Content-Provider. SQLite only storage data for the app who creates it
I read this answer while looking for same doubt, so thought of sharing it.
it states -
It's good practice to provide the extra level of abstraction over your data to make it easier to change internally. What if you decide to change the underlying database structure at a later time? If you use a ContentProvider you can contain all the structural changes within it, where as if you don't use one, you are forced to change all areas of the code that are affected by the structural changes. Besides, it's nice to be able to re-use the same standard API for accessing data rather than littering your code with low-level access to the database.
So, using a content provider would be a good idea.
Think of advanced Content Management Systems. Each object (page, image, news article, event item, etc.) has a content, an address, user permissions, and ways to interact with it from different parts of the system. Content Providers do that for Android. You can now share files or images you may have stored in your application. You can also create custom sharable objects, like bussiness contacts, editable notes, etc. And specify security and the default application to deal with such object when you open them from any other application.
One difference is that Content Providers have platform support for Content Observers. Your going to need to implement your own Observable pattern for a SQLite database.
How to automatically re-query with LoaderManager
ContentObserver for SQLite?