You should close SQLiteDatabase objects in Android developing (2)

“SQLiteOpenHelper” may return the same “SQLiteDatabase” object. Based on this, I will describe how to execute close() properly.

“SQLiteOpenHelper” returns the same “SQLiteDatabase” object

Before, in my article You should close SQLiteDatabase in Android developing (1) | DeVlog, I said you should close “SQLiteDatabase” object properly.

Then, I found that the objects obtained from “SQLiteOpenHelper” may be the same “SQLiteDatabase” object. That is, “SQLiteOpenHelper” object holds mDatabase field which is the “SQLiteDatabase” object and returns it.

You can be addressed with the same idea

However, the way of action is almost same to [Pattern 1] – [pattern 3] of the previous article. You shoud close properly.

[Pattern 1]
Get one “SQLiteDatabase” object from one “SQLiteOpenHelper” object when you need it, and close it when you no longer need it. I take this style basically.

This is as a previous article.

By the way, even if you close a “SQLiteDatabase” object that is obtained from a SQLiteHelper object and then you get a “SQLiteDatabase” object from the same Helper opbject, there is no problem. In that case, new “SQLiteDatabase” object will be created.

[Pattern 2]
If you retrieve multiple objects from a single “SQLiteOpenHelper” in one thread, you should call close() at once when no longer needed. To do so, use “SQLiteOpenHelper#close()”. It will close the “SQLiteDatabase” object inside.

[Pattern 3]
If you want to use “SQLiteDatabase” object obtained from a “SQLiteOpenHelper” object in multi threads, you should use the “aquireReference()”.

db1 and db2 in [Pattern2] or mDb1 and mDb2 in [Pattern3] looks different each other, but are the same entity. Therefore, their handling is the same as when dealing with multiple references in the previous article.

[Reference Sites]

  1. SQLiteOpenHelper | Android Developers
  2. SQLiteDatabase | Android Developers

[Relative Article]
You should close SQLiteDatabase in Android developing (1) | DeVlog

You should close SQLiteDatabase objects in Android developing (1)

Close “SQLiteDatabase” properly and reliably

I have developed an Android application that uses SQLite and checked the log after leaving it for a while to run. Then I found warnings in logs below.

W/SQLiteConnectionPool(1261): A SQLiteConnection object for database ‘/data/data/…..’ was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.

Unfortunately, it is not mentioned in particlular Storage Options | Android Developers that you should close database objects.

So, I looked at the source code of Android and studied how properly and reliably you shoud close “SQLiteDatabase” objects. I will describe below.

Looking at the source code, “SQLiteDabase” object is managing the internal reference counter. So, even if you would call “close()” of the object, the object will not call “close()” of inner native code on its own side as long as the counter is not 0.

Therefore, for one “SQLiteDatabase” object, it is important to call “close()” of the appropriate number of times. Perhaps exceptions is thrown if you call it much times. And objects are leaked if you call it less times.

3 Patterns to close “SQLiteDatabase”

I think it is a good idea to follow the following principles.

[Pattern 1]
Get the object at the time of use and close it when you have finished to use it.
This is the most simple and safe way. With “try” – “finally”, you can execute “close()” for sure.

[Pattern 2]
Keep the “SQLiteDatabase” object to an instance field and call “close()” only once at the end.
If you concern the cost to obtain the object eatch time, this method would be good. In the “Service” or “Activity”, you should call “close()” in “onDestroy()”.

[Pattern 3]
If you pass a “SQLiteDatabase” object to the other thread, you should call “acquireReference()” method in the original thread and call “close()” in the new thread.

Because “acquireReference()” method increments the reference counter, you must call “close()” one extra. If you call “close()” in both the original thread and new thread, actual “close()” is performed. There is no problem if you call “close()” in any order.

In this way, in using the “SQLiteDatabase”, if you call “close()” when they are no longer needed, you can avoid the leak.

In addition, “Cursor” objects, which is used to perform query, also should be closed. But I don’t think you should pass them to another thread because there is no method that corresponds to “aquireReference()” of them.

[Reference Site]
You should close SQLiteDatabase in Android developing (2) | DeVlog