I'm trying to access since different activities to an unique database, however when I work with databases I have to create a different database instance since every activity and this produce an unwanted result, how can i manage an unique database since different activities?
however when I work with databases I have to create a diferent
database instance since every activity and this produce an unwanted
result, how can i manage an unique database since diferents
activities?
So did you think about Singleton? I think your problem is directly designated for an usage of Singleton design pattern. An usage has only benefits(always only one instance, not wasting of memory, clean and human-readable code etc.).
Let's write some code:
private static SQLiteOpenHelper instance;
public static SQLiteOpenHelper getInstance(Context c) {
if (instance == null) {
instance = new SQLiteOpenHelperImplementation(c);
}
return instance;
}
I have only good experiences with Singleton.
Notes:
To improve your work with database i have a few suggestions for you:
If you have more than one table, i suggest you to create "operation"
classes which will wrap CRUD operations and specific methods for each
table.
To improve performance, security and integrity of db always use
TRANSACTIONS. It's very useful and efficient practise
In concurrent programming, always use synchronized blocks and methods to avoid problems related to access to database and making changes
Always when work is done, release your cursors and close database
Related
I'm using SQLite-Net-Pcl in Xamarin.Forms application, I have created a singleton dataStore class for all my database methods. What is the best practice for creating a SQLiteConnection? Should there be a private readonly connection object on your class and use it in all your db operations. Or should you use create a new SQLiteConnection in every method? Also should I use a lock() statement around my db code?
lock(lockerObj)
{
// db code
}
That depends a lot on the nature of your data and the nature / complexity of your application.
For us we have had no issues using a single connection and using the lock statement to help ensure serialized updates to the database. That is the simplest to implement and manage since you don't need to be concerned with connection isolation.
But that is not a one size fits all solution.
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.
Maybe I'm missing something but my question is: can I access the database from different points of my code each one using its own DatabaseHelper instance? Or is it better to have a unique global static DatabaseHelper accessible from everywhere (threads, activities, ...)? What is the best practice in this case?
It is better to have a single instance if you are using multiple threads, as thread synchronization will be applied automatically. Whether that single instance is a singleton or wrapped in a ContentProvider is up to you.
There have been a few questions on this topic but none giving firm reasons for why there should or shouldn't be a single or multiple instances of the databaseHelper.
When is it a good idea to have multiple instances of DatabaseHelper and when is it not. Is less complexity (if that is actually the case ) a good enough reason to have just a single instance ?
Your DatabaseHelper should be a singleton for sure. Each helper maintains the single connection to the database. If you have multiple helpers with connections to the same database, then concurrency issues will result. Sqlite does it's own locking underneath the single connection to ensure proper concurrent access to the database so using that single connection (and therefore that single helper) for all of your database operations is recommended and required.
Use one DatabaseHelper for each database in the application. SQLite takes care of file locking for you (many reads, only one write) and Android using Java locking in SQLiteDatabase. However, you can still get have a concurrency failure (simulataneous connections writing at once). It's the multiple connnections part that you want to avoid and that is what is managed by one instance of the DatabaseHelper.
I'm currently grokking the SQLiteDatabase and related classes with the purpose of getting a better understanding of how it handles concurrency (my current solution works, but I got the impression I might actually be doing redundant work, since its done with the presumption that concurrency is not handled for me).
Right, about the android documentation for SQLiteOpenHelper states the following about the getWriteableDatabase method
Once opened successfully, the database is cached, so you can call this
method every time you need to write to the database. (Make sure to
call close() when you no longer need the database.)
It's a little unclear to me what is being cached(so I currently have a wrapper that does the caching for me). So, what is going on here? Are the two SQLiteDatabase instances wrappers around a cached/static instance?
Also, how is the actual locking handled? If I have two separate SQLiteDatabase instances, created by the same SQLiteOpenHelper instance, are these then transactional safe? As in if i begin a transaction in exclusive mode on one transaction, and then start another transaction in another thread, on the other SQLiteDatabase instance, I would expect the second one to not start until the first one is done. Is this how it works?
"Caching" .. well, I guess you could call it that. The SQLiteOpenHelper typically has a single SQLiteDatabase stored internally (since the last call to create a db), so calling #getWritableDatabase() twice will give you the same object the 2nd time (unless you closed the first instance - then it will create it again). Actually, calling #getReadableDatabase() will attempt to open the database r/w and only fall back on returning a read-only instance if that fails.
Note, closing databases & calling #getWritableDatabase() is not thread-safe - i.e. the SQLiteOpenHelper can return closed databases if you mess with it in many threads.
In short, you're going to have a single instance of SQLiteDatabase - but you can enable locking - making it thread-safe - by calling SQLiteDatabase#setLockingEnabled(true).
It's a little unclear to me what is being cached(so I currently have a wrapper that does the caching for me).
The SQLiteDatabase object is cached.
If I create two SQLiteDatabase instances with this method, and close one, the other one is still open.
Assuming you have just one SQLiteOpenHelper, you cannot "create two SQLiteDatabase instances with this method". The second getWriteableDatabase() call returns the same SQLiteDatabase as does the first call.
If you are only accessing the database from a single component (e.g., just one activity or just one service), use one SQLiteOpenHelper (and, by extension, only one SQLiteDatabase), held by that component. If you are accessing the database from multiple components, you will need to go with a singleton SQLiteOpenHelper instance, either directly or by means of wrapping your database in a ContentProvider.