I have many Fragments in a ViewPager in my app. At the start of the application three of them try to connect to database to retrieve data.
For database handling I use a singleton pattern with SQLiteOpenHelper. When I need my database I call it like this: SQLiteDatabase db=DatabaseHelper.getInstance(this.getContext()).getWritableDatabase();.
The problem:
If I don't close the db with db.close() I get a android.database.sqlite.DatabaseObjectNotClosedException of course. So I do.
But as it's a singleton approach, when one of my Fragments finishes to fetch the data, it closes the database and the rest of Fragments can't use it.
Checking if the databse is open on every iteration when I read something from it seems very redundant. What else can I do?
Related
i want to add data in 3 tables in one database from 3 AsyncTask object. because the AsyncTask objects may run or finish at the same time and i'm adding data in my database in onPostExecute() , i want to know is it possible to do such a thing or not ?
thanx
Android SQLiteOpenHelper is synchronized by default. all you need to do is make your DB helper singleton and you will not face any problem.
Read this for more info on singleton db helper.
In the onCreate() method of my main activity I call the constructor of my dbManager, I call the open function that creates an instance of a SQLiteOpenHelper and than I call the getWritableDatabase() on it.
Within the UIThread I add records to the database and save those records to an ArrayList. Two other threads check the ArrayList do stuff and than update the list and the database.
Now I want to add a button in the UI to delete both database and list records using an AsyncTask.
I've read that the SqliteOpenHelper object holds on one database connection. So if there is one helper instance there is only one db connection. This connection could be used from multiple threads and the SqliteDatabase object uses java locks to keep access serialize. So If I have multiple threads writing on the database, a thread will wait until the previous one has finished his operation?
Adding the new functionality (remove all) could create problems, because I have to avoid that one of the two threads may try to edit a record that no longer exists. How can I achieve my goal? Thanks.
The databese:
As long as you use only one helper, you are thread safe without a need to do anything.
In a multi threaded app, you'll need synchronized only on the creation of the helper.
You can use transacion if you want to define a critical section (more than one atomic operation).
Wrap each call with getWritableDatabase() and close(false):
public void doSomething() {
SQLiteDatabase tdb = getWritableDatabase();
dbInstance.writeSomething(tdb, 1);
close(false);
}
In this way I have multiple threads reading and writing to the database without any problem.
You app logic:
Use memory to keep track of object state, and use the database as storage only. So if one thread deletes rows from the database - you can immediately update your objects in memory, and handle your ui accordingly.
If your data is very large, than you can keep in memory only a SparseArray of dirty rows id.
It may be useful to synchronize some operations here.
So If I have multiple threads writing on the database, a thread will
wait until the previous one has finished his operation?
Doesn't need to be so. See this for more details. Anyway, this is up to the DB engine and should be transparent.
Adding the new functionality (remove all) could create problems,
because I have to avoid that one of the two threads may try to edit a
record that no longer exists. How can I achieve my goal?
Have only one thread update the DB. Other threads only modify the ArrayList -also watch out because ArrayList is not thread-safe, consider using Collections#synchronizedList().
I've done my homework; I know all the ways to query an SQLite db from an Activity.
The problem is that all the examples ASSUME that i want to "load" data from the db onto the FIRST Activity screen.
But when my app's FIRST Activity is loaded I DON'T WANT TO GET ANY DATA FROM THE DB; i just want to:
(1) Check if the db file has already been created (if the setup routines have already run).
(2) If the db exists, load the SECOND Activity (with ContentProvider/Loaders, etc.) so the user can start adding data.
OR
(2) If the db DOESN'T exist, WHILE STILL IN THE FIRST ACTIVITY run the setup routines (create the db/tables from an *.sql file & INSERT the dummy data where needed)...then load the SECOND Activity (with ContentProvider/ Loaders, etc.) so the user can start adding data.
To me, the simple operation of creating the db/tables shouldn't require all the OVERHEAD of a ContentProvider and a bunch of Cursors and Loaders.
Is there anybody who could point me to a SIMPLE solution? Thanks!
Yaqub's link was helpful...
...what i did was create public static final String arrays in a DBConstants class containing the commands to create the Database on first run.
I have huge databases (~ 40K rows) which I deal with in my app. There is one activity which has a list view that uses a CursorAdaptor to display and search in the whole database rows. Each time the user deals with a database, I open the database and create the required Cursor and I call Cursor.getCount() in another thread to tackle the laziness issue of cursors and make it fully ready for future operations. It takes around 7 seconds to have Cursor.getCount() done for the huge databases.
Users may invoke this activity multiple times so I store the cursor in a global class as a static data member and I always reuse the same cursor.
I guess that if I did not close the cursor and the database properly I may get weird results. Right?!
My question is: When I should close the cursor and the database?
It will not be possible to close the database and the cursor in Activity.onStop() since I will have to re-open the database and the cursor each time the activity goes from being invisible to visible. And if I did the close in Activity.onDestroy, then the app might be killed by the OS (when device's available memory is low) before the onDestroy is called.
Why don't you turn this global static class into a singleton so that you don't run into instantiation problems, which it sounds like you are referencing. Once you call getInstance() in your singleton you will always get the same cursor and DB connection within that class.
According to http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#getWritableDatabase%28%29
Once opened successfully, the database is cached, so you can call this
method every time you need to write to the database.
Consider the following snippet:
SQLiteDatabase db1 = openHelperImplObj.getWritableDatabase();
// do something with db1
SQLiteDatabase db2 = openHelperImplObj.getWritableDatabase();
// do something with db2
db2.close();
// do something with db1
db1.close();
I presume the second call to getWritableDatabase() will return the same cached DB (the db1), wouldn't the line db2.close() cause any issue to db1 operations that happen afterward? If so, what is the recommended way to avoid such problem since the second call may happen anywhere, i.e. in a different function or even in different class.
When you open a data base by using db openHelperImplObj.getWritableDatabase();
then following thing check
1>If database is not created then it create database and open it for write mode else created first then open.
2>Second and most important what i have observed if data base is already created then it opened it but if its open already it do nothing, That means it occupy the old instance of data
base that open DB already until you close it.Thats why its better practice to close DB once it
use over
Hope you got