I am using SQLiteOpenHelper class to create, open database. for my application i am creating writable object SQLiteDatabase which i am using to read and write data to database. This object is static for main class and used in all application to read write in to database. my application is working properly on emulator. but on device after some read write query fires. why it is happening, please if any one has solution help me.
It is not recommended to have the helper as a static instance. Rather you should instanciate it each time you need to acces the DB. What might be happening is that your DB connection is getting closed by Android (because it needs memory, because there are too many open connections, ...) and when you do a query, you do not check that the connection is still open.
You can read this tutorial to get the idea of how to do it properly.
Basically inside an activity, the idea:
private void reloadData() {
MyDBHelper db = new MyDBHelper(this.getApplicationContext());
db.open();
Cursor c = db.query(...);
db.close();
// Update your data using the cursor
}
I had the same problem a few weeks ago, and I found this page, it's exactly what's wrong. The SQLite is buggy in Android and is implemented the wrong way, so you can't have threads reading and writing to the database/table at the same time.
setLockingEnabled() just dont work the way it's supposed.
What I did was running all methods that read and write to the db "Synchronized" which means you'll never have a problem with reading or writing data at the same time no matter how many threads you have.
Regards
Tobias
Related
Ive done a lot of Googlig on this topic and I'm confused as to best practice.
Initially I had:
A) Created a DataBase object in my main class header area and then just passed it to functions as needed. I then later read that a DataBase should be opened and closed each time before use.
so then I:
B) went to each function (passing Context) which uses a SQL command and created a new DataBase object, created a filled cursor via SQL, and then closed the Database before returning. However, I then later read that it's expensive to do this.
now i'm thinking that:
C) I should create a new Database object in each subclass that uses one, and open and close it as needed.
Im sorry for the noob and seemingly design question (delete it if it's out of scope of StackOverflow), however, I truly am confused of how this should be handled to avoid errors, and how Google wants us to do it.
Regards
The Android docs recommend using an SQLiteOpenHelper, which caches the database object. From the SQLiteOpenHelper reference:
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.)
So, I'd go for a singleton carrying an instance of SQLiteOpenHelper, so you can access it from anywhere. Then get the database where you need it, and close it on exit points of your application (if any). That way you only open a database if required, but can re-use the same connection for other tasks as well.
If you do only need the database for single tasks and/or there are other Applications accessing the same database, you may consider closing it directly after your database-tasks are done; there is a discussion about closing in another question.
I was looking for a solution for making my slqite database, accessing syncronized and avoid problem with open/close connection, and I falled in this good answer:
In this solution, however, there is not a explicit closing of database.
many argue that this is not a problem, but I would know how can I close the connection after the application is stopped.
note: In the aforementioned link the author of the answer suggest this:
With my implementation the singleton lives for the life of the
application. Therefore I did not implement an explicit destructor,
instead, in the app shutdown code (or crash handler) the database is
explicitly closed. See Thread.setDefaultUncaughtExceptionHandler()
which I used in ApplicationContext.onCreate() after I posted my sample
code.
Can be this a good solution? If yes, how can I manage Thread.setDefaultUncaughtExceptionHandler() ?
EDIT:
I want also, that if the database resource is not available, the requiring thread will wait until the database is released. Can I use this code? the isDbLockedByOtherThreads() is deprecated
private myDatabase(){
final DbHelper mDbHelper =new DbHelper(ApplicationFramework.getContext());
mDB = mDbHelper.getWritableDatabase();
while(mDB.isDbLockedByCurrentThread() || mDB.isDbLockedByOtherThreads()) {
//db is locked, keep looping
}
}
You need not to worry about closing database connection after the application is stopped it automatically gets closed.
Actually there is only one connection internally, you make its different instance thats a different thing. Thats why many people says closing of database connection does'nt make any sense.
Always have a single static object of database connection it will be safe and less exception prone, and don't worry about closing it.
If you try to write to the database from actual distinct connections at the same time, one will deifnately get failed . It will not wait till the first is done and then write. It will simply not write your change. Worse, if you don’t call the right version of insert/update on the SQLiteDatabase, you won’t get an exception. You’ll just get a message in your LogCat, and that will be it.
Answer for updated query
Use only Single static instance of your db connection no need to make others threads, all operations will be automatically synchronised.
I have a problem with my database.
Basically my applications read texts and rates of text from my SQLite database and show it on screen. I have also Thread function which downloads content from external internet server and uploads it into the database.
On less popular devices (mostly tablets) it generates errors like:
DB close exception
DB locked
Someone advised me to create something called a singleton to handle this and I created it but it generates errors. So I have an idea to use AsyncTask instead of Thread; do you think it will help?
Maybe you have other solutions?
AsyncTask will not help you here. You have to create a database connection as a singleton.
You should get a readable database for when you are reading and a writable database for when you are writing. Then you will be able to do both at the same time.
Both of the methods are in the SQLHelper class
Never close the DB. Make sure you have only one Helper instance per application.
See this for reference SQLiteDatabase close() function causing NullPointerException when multiple threads
This may help you :)
I'm working with SQLite in my android project. There is a feature that is clear to me -- if there are multiple threads working with DB then they should use only ONE instance of DBHelper and SQLite guarantee a safe access (even if it is concurrent) to the DB.
But I still have one thing needed to be clarified. How should I manage with DB connection (SQLiteDatabase object)? How often should I call geWritableDatabase() and close()? Is it ok if I call these methods once? Or it's better to obtain SQLDatabase object and close one every time I perform read/write operation on DB?
It is handled by default... I mean if a writtable database open, whenever you try to access read-only database it closes writtable one and create new read-only database instance. As far as i know :)
We all learn that resources, such as database connections, should be acquired late and released early.
Yet applying this principle to SQLite database connections on Android have caused me some headache.
I have an app that download updates from a backend server in a service working in the background, writing updates to the database at a regular basis. The problem I experience arise when the following sequence occurs:
Service opens a writable database connection
Some activity opens a readable database connection
Service closes its database connection concurrently with the activity reading data
Activity fails due to its database connection was closed
Both the service and the activity uses the same SQLiteOpenHelper class, though different instances, to open their connections. My initial assumption was that this should work just fine, but somehow it seems that the underlying connection is shared between the two database instances.
To work around the problem I ended up not closing the database objects, only closing any opened cursors. This seems to work, though I'm not sure that I'm not leaking memory here.
Is there something obvious I am missing here?
Is there something obvious I am missing here?
I'd say no. Looking at the source code to SQLiteOpenHelper, I can't see how two instances could be sharing a SQLiteDatabase object.
Some diagnostic suggestions:
Dump the toString() value of each SQLiteDatabase, which should give you a Java instance ID. If they are the same, that is where your problem lies, and you will need to work your way upstream to figure out how the heck this is happening (e.g., you really are using the same instance of the SQLiteOpenHelper).
With your database in a stable state (i.e., no need to create or upgrade), flip one of your two database spots to use SQLiteDatabase directly, rather than via SQLiteOpenHelper, and see if that changes matters.