Best place to close database connection - android

I was looking for a while for answer on my question but I didn`t get what I need. I have an application with a ListView, and form where I can add new record to DB. So there is not much queries to do.
How to handle connections to db ? Should I close it after getting what I want or should I keep it open whole time until app is closed ? I want to know what is the best way while thinking about performence and battery life.

According to this post by a Google engineer (Dianne Hackborn), there's nothing wrong with leaving the database connection open:
Android made a deliberate design decision that is can seem surprising,
to just give up on the whole idea of applications cleanly exiting and
instead let the kernel clean up their resources. After all, the
kernel needs to be able to do this anyway. Given that design, keeping
anything open for the entire duration of a process's life and never closing it is simply not a leak. It will be cleaned up when the
process is cleaned up.
So, for simplicity, I would extend the Application class to provide a single well-defined entry point for your code, and open the database connection in its onCreate(). Store the DB connection as a field in your Application, and provide an accessor method to make the connection available to rest of your code.
Then, don't worry about closing it.

In general I'd close the connection in the onDestroy() function of the Activity which opened the connection. I'd close() a cursor from a database in the function which uses the cursor.
public MyActivity extends Activity{
private myDatabase mDatabase; // myDatabase extends SQLiteOpenHelper
private Cursor mCursor;
public MyActivity(Context context){
super(context);
initMemberVariables();
}
public ElementButton(Context context, AttributeSet attrS){
super(context, attrS);
initMemberVariables();
}
public ElementButton(Context context, AttributeSet attrS, int defStyle){
super(context, attrS, defStyle);
initMemberVariables();
}
private void initMemberVariables(){
mDatabase = new PSEdb(this.getContext());
}
private void getData(){
mCursor = mDatabase.MyGetterFunction();
while(mCursor.moveToNext()){
try{
// populate your data
}catch(CursorIndexOutOfBoundsException ex){
// handle the exception
}
}
mCursor.close();
}
#Override
public void onDestroy(){
super.onDestroy();
mDatabase.close();
}
}

Establishing the connection to the database is expensive. If connections are not in short supply, and the database is local, I'd keep the connection open rather than establishing it for each write operation to the database, as you'd typically do in a client-server application that needs to scale to accommodate a large number of concurrent users.

Related

how to make SQLite connections more efficient

Is there any advantage in keeping a local sqlite connection open the entire time that the activity is running?
I usually create a new connection and then close it within every method that does a database operation. It would look something like this :
myMethod(Context context){
LocalDBHelper localDBHelper = new LocalDBHelper(context); //extended SQLiteOpenHelper
SQLiteDatabase db = localDBHelper.getWritableDatabase();
...
localDBHelper.close();
}
So in a typical user session, this would happen around 10 times. Would it make sense to create a connection in onResume(), use that in all the database access methods and finally close it in onPause()?
Is there any advantage in keeping a local sqlite connection open the entire time that the activity is running?
You usually want one "connection" for the entire life of your process. In particular, you do not want to have multiple "connections" in use simultaneously across multiple threads. All of the thread-safety logic for SQLite in Android is based around using a single SQLiteDatabase (and, hence, single SQLiteOpenHelper) for all of those threads, so proper locking can be done.
Based on #CommonsWare answer, i have implemented a Singleton pattern to have a single application wide instance of LocalDBHelper using lazy instantiation. It works fine till now and avoids the need to instantiate and close the helper/database for every operation.
public class MyApplication extends Application{
private static MyApplication instance;
public MyApplication(){
instance = this;
}
public static Context getContext(){
return instance;
}
}
public class LocalDBHelper extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "MyDB";
private static final String LOG_TAG = "LocalDBHelper";
private static LocalDBHelper instance = null;
/*private constructor to avoid direct instantiation by other classes*/
private LocalDBHelper(){
super(MyApplication.getContext(), DATABASE_NAME, null, DATABASE_VERSION);
}
/*synchronized method to ensure only 1 instance of LocalDBHelper exists*/
public static synchronized LocalDBHelper getInstance(){
if(instance == null){
instance = new LocalDBHelper();
}
return instance;
}
...
...
}
Usage :
SQLiteDatabase db = LocalDBHelper.getInstance().getWritableDatabase();
db.insert(...)
Usage with transactions :
SQLiteDatabase db = LocalDBHelper.getInstance().getWritableDatabase();
db.beginTransaction();
try{
....
...
db.setTransactionSuccessful();
}catch(Exception e){
e.printStackTrace();
}
finally{
db.endTransaction();
}
Important : No need to call localDBHelper.getInstance().close() anywhere
As your app works on the same machine every time it is luanched and the same memory is accessed every time, so there will be no problem to let it be open. because in the same memory space , sqlite just loads like a DLL for a main application.
Just one problem may occur! when you wanna run many threads for accessing database at the same time(for example with AsyncTask) the interference between them forces some threads to stop! so its better to make connection for new threads eachtime!
Personally I find it easier to call the SQL Connections required on the initial app load, to store into the SQLite DB's, and either set a refresh button for the user to decide when they want to refresh the data, OR set a periodic update interval timer for the application.
By doing it this way, you are increasing performance during general usage of the app by placing the data load on a pre/user defined time.
Although I do suppose this depends on how often a DB Interaction is going to be performed....
This Question may ahve some useful answers for you:
Should I open() and close() my SQL database constantly or leave it open?

Correctly open/close a database with Singleton design pattern

I am creating an application which makes a lot of interactions with a database (both read and write operations).
To avoid open/close operations at each request, I created a class extending SQLiteOpenHelper with a Singleton design pattern. This way, I am sure only one instance of the SQLiteOpenHelper and only one connection to the database is made during all the application lifecycle (and not only activity lifecycle).
I also read some articles about ContentProvider, but I am not sure it's a better way.
So, this is the main logic of my Singleton class (onCreate and onUpgrade removed) :
public final class BaseSQLite extends SQLiteOpenHelper {
private static BaseSQLite mInstance = null;
private SQLiteDatabase db = null;
public static BaseSQLite getInstance(Context context) {
if (mInstance == null) {
mInstance = new BaseSQLite(context.getApplicationContext(),
DBNAME, DBVERSION);
}
return mInstance;
}
private BaseSQLite(final Context context, final String name,
final int version) {
super(context, name, null, version);
db = getWritableDatabase();
}
#Override
public synchronized void close() {
if (mInstance != null)
db.close();
}
public Cursor getAllData() {
String buildSQL = "SELECT * FROM myTable";
return db.rawQuery(buildSQL, null);
}
}
So, to access my database, I made this :
BaseSQLite baseSQLite = BaseSQLite.getInstance(context);
baseSQLite.getAllData();
It works perfectly for now. But my question is about the close() method. I really don't know when to call it. Actually, my database instance is the same for every Activies of my application, so I think it's a bad idea to call close() in an onPause() method, because the instance will be potentially (and it will often happens) recreated in the onStart() method of the next Activity. Also, I can't detect the end of my application, i.e. when no activity is visible on the screen anymore.
Can somebody give me some help about this issue ? I found some answer when the database is linked to ONE activity, but no really hint is given for my case.
You should call close anytime you are done writing to your database. For example when you insert data, you will have an open connection to the database that should be closed when it is done.
Reading is different. When you create a SQLite database on your phone, the data is persistent. The database exists and the handler you create provides a convenient way to access that information. Reading the database usually takes place by getting a readable instance of the database and using a Cursor to extract values. In that case you close the cursor when you're done, not the database itself.
You're right that you should not be closing the database connection during separate activities' lifecycle methods. Instead, as suggested above, close the database connection in your handler's methods that write to the database when you are done performing that transaction.

SQLiteOpenHelper synchronization

So I've come up with some idea and I'm wondering if it is realizable.
Let's say I've multiple tables(database models) each of them is represented by some class.I don't wont to use singleton pattern with the open helper so I've created some simple class to provide single instance of the database.My idea is that as long as all tables hold reference to SQLiteDatabase(returned by the open helper) they will all work with the same DB instance and probably won't be needed to synchronized the work with the database since the open helper do this.When the last table finish it's work the GC will collect the open helper (since the last reference will be weak reference) -> finalize() is called and I close the db during this method to prevent any warning from OS. My question is: Is this could work?Will it close automatically the DB and will it leak or throw some exception?
Here is my class:
public class DatabaseHelper {
private static WeakReference<SomeCustomOpenHelper> sDBOpenHelper;
private void notifyDBCreate(SQLiteDatabase db) {
for (DBTable table : mTables) {
table.onDBCreate(db);
}
}
private void notifyDBUpgrade(SQLiteDatabase db) {
for (DBTable table : mTables) {
table.onDBUpgrade(db);
}
}
public SQLiteDatabase getDatabase(boolean readOnly) {
SomeCustomOpenHelper dbHelper = sDBOpenHelper.get();
if (dbHelper == null) {
dbHelper = new SomeCustomOpenHelper(context, name, factory, version, new DatabaseEventsCallback());
sDBOpenHelper = new WeakReference<SomeCustomOpenHelper>(dbHelper);
}
if (readOnly) {
return dbHelper.getReadableDatabase();
} else {
return dbHelper.getWritableDatabase();
}
}
private class DatabaseEventsCallback implements IDatabaseEventsCallback {
#Override
public void onCreate(SQLiteDatabase db) {
notifyDBCreate(db);
}
#Override
public void onUpgrade(SQLiteDatabase db) {
notifyDBUpgrade(db);
}
}
interface IDatabaseEventsCallback {
void onCreate(SQLiteDatabase db);
void onUpgrade(SQLiteDatabase db);
}
private static class SomeCustomOpenHelper extends SQLiteOpenHelper {
private IDatabaseEventsCallback mCB;
public SomeCustomOpenHelper(Context context, String name, CursorFactory factory, int version, IDatabaseEventsCallback cb) {
super(context, name, factory, version);
mCB = cb;
}
#Override
public void onCreate(SQLiteDatabase db) {
mCB.onCreate(db);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
mCB.onUpgrade(db);
}
#Override
protected void finalize() throws Throwable {
this.close();
super.finalize();
}
}
}
Did not really know the answer neither, but got interested and looked it up.
The answer is written out properly here;
http://blog.foxxtrot.net/2009/01/a-sqliteopenhelper-is-not-a-sqlitetablehelper.html
But basically the core of the info is;
I created three SQLiteOpenHelper classes, one for each table, even though they all referenced only a single database file.
Here is where everything fell apart. Android maintains Versions for databases based on the package it’s associated with, the name of the database, and the version number you provide. The package and name go into decided what the path on the device will be, while the version is stored (somewhere) on the device so that it knows when it needs to call an OpenHelper’s onUpgrade event handler. It turns out that if, in the SQLiteOpenHelper Constructor, it determines that the database already exists, it won’t call your onCreate or onUpgrade methods at all, even if the particular class which is making the call has never been called before.
I've been through the same issue when I was working on a project. I also went crazy on the doubt if the static instance was using enough memory and causing a considerable memory leak.
I'm not sure if creating a weak reference would guarantee that database instance would be collected. However a possible workaround could be : Assigning a null value to static database instance once your all database transaction is done and you've close the database. This might ensure that the database instance no more allocates any memory.
Let me know if this works or if there is a better work-around.
You can do so. As you say the locking should be happening on the SQLite and I've never heard issues around that so you should be fine with this.
The only restriction you have is that all the tables will have to go into the same database since Android for now just allows you to have one file.
Closing the database is a different thing, that's why it is actually interesting to use the singleton pattern (you avoid closing + opening all the time).
Nonetheless with your approach you just need to make sure to close the db whenever you are done with it. As far as I'm concerned this is not automatically done.
Additionally Lars Vogel has written extremely useful and detailed articles around DB access in Android. You might want to have a look there. http://www.vogella.com/articles/AndroidSQLite/article.html
you can use one open helper for all the table .i am using the single instance in my app also like this .
public static synchronized DatabaseHelper getInstance(Context ctx)
{
if (dbhelper == null) {
dbhelper = new DatabaseHelper(ctx);
}
return dbhelper ;
}
My question is: Is this could work?Will it close automatically the DB
and will it leak or throw some exception?
NO it will not close automatically database , when your application will demand for DATABASE object and OS found some of your database instant are alive then Android framework try to connect that object reference (which is probably weak reference )
and i have to say , I don't recommend opening and closing a DATABASE on-demand or temporarily . It is always nice to open the DB up early and keep it open for the duration of your whole activity and close it when the activity gets finished or suspended .

SQLite database in separate class vs. in same class, which is better? Android

I have an SQLite database that is in a separate class from the main class that extends Activity.
I noticed that there are two ways of setting up the database. one way is to put it inside the main Activity class, either in the class or as a nested sub class. the second way is to put it in the separate class.
the separate class looks better, however there is one disadvantage. You have to create an instance of it in the main activity class every time you want to do something. I read that instantiating objects in Android is expensive and should be avoided.
despite this, I would rather make the database as a separate class. Is the cost of instantiating objects enough that it makes putting the database in the same class a better deal?
example of separate class for SQLite database: incomplete psudo-code
public class SQLiteDB {
private static class DbHelper extends SQLiteOpenHelper{
// db helper methods
}
// methods for DB, like get, set, and others
public void openDatabase(){ }
public void closeDatabse(){ }
public void insertRecord(String record){ }
}
example use in main Activity: incompete psudo-code
public class Main extends Activity{
// every time I want to use it I must instantiate an object for the database class
// many instances of SQLiteDB object created, garbage collector works hard
SQLiteDB mDatabase = new SQLiteDB();
openDatabase();
insertRecord("insert this");
closeDatabase();
}
SQLite database in separate class vs. in same class, which is better?
This is very comprehensive question and it depends on more factors(type of application, personal requirements, how you'll deal with db etc.). Somebody can prefer to place database as inner class and someone as separated class. Problem is that many developers are trying to "stick" as much code as possible into one class and maybe they "fear" to create a little more classes. I don't know that exactly. I mentioned that only as my personal note.
But let's back to your question. What is better?
I think that approach with separeted class. You should let your Activity classes only "Activity classes" > only for creating and dealing with UI. Application appearance should be separated from application logic. If you'll follow this "rule" your code will become more clean and human-readable(if someone else will look at your code he shouldn't be completely lost). It's not a shame to have 20 purely written classes as to have all stuff sticked in one class(like a pig).
however there is one disadvantage. You have to create an instance of
it in the main activity class every time you want to do something. I
read that instantiating objects in Android is expensive and should be
avoided.
Did you think about an usage of Singleton? This design pattern is worth to think about it. You will always have only one instance that have many benefits e.q. no waste of memory. I have only good experiences with Singleton. Therefore i recommend you to try and use it.
Example:
private static SQLiteOpenHelper instance;
public static SQLiteOpenHelper getInstance(Context mContext) {
if (instance == null) {
instance = new SQLiteOpenHelperImplementation(mContext);
}
return instance;
}
And at the end i give you a few suggestions:
Everytime you'll work with cursors, databases etc. release / close
them immediately after work is done. This can solve many exceptions
related to SQLiteDatabase and Cursor
An usage of synchronized blocks and methods is pretty good practise
in the case of concurrent programming to avoid many problems
If you have more than one table in database i suggest you create
"serving" class for each table that will wrap CRUD operations and specific
methods of the table
Before Activity is destroyed, check and release all sources which are not
already released.
I prefer the solution you gave here. The primary advantage is that you can easily access the database from any Activity (or other class) in your app. To solve the problem of creating a new instance every time you use the database, you can instead create a single instance in onCreate(), use the database all you want while the Activity is active, and finally close the database in onDestroy().
This would be a matter of personal taste.
However, what I've found to be efficient and clean has been to create a class that extends SQLiteOpenHelper. In this class you will end up writing the SQL code to create your tables and writing methods as your stored procedures.
The class would look something like this:
public class DatabaseInterface extends SQLiteOpenHelper {
// Database version
private static final int DATABASE_VERSION = 1;
public DatabaseInterface(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//in your oncreate you will write the queries to create your tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_NEWS = "CREATE TABLE News(id INTEGER)";
db.execSQL(CREATE_NEWS);
}
// upgrading tables
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// drop tables if exist
db.execSQL("DROP TABLE IF EXSIST " + NEWS);
// recreate tables
onCreate(db);
}
Consider we have a News obj that takes 1 param as it's constructor, your stored procedures can look something like this:
public ArrayList<News> getNews() {
ArrayList<News> mNewes = new ArrayList<News>();
SQLiteDatabase db = null;
Cursor cursor = null;
try {
String sQry = "SELECT * FROM " + NEWS;
db = this.getWritableDatabase();
cursor = db.rawQuery(sQry, null);
if (cursor.moveToFirst()) {
do {
mNewes.add(new News(cursor.getInt(0)));
} while (cursor.moveToNext());
}
} catch (SQLiteException e) {
Log.e("SQLite - getNewes", e.getMessage());
return null;
} finally {
cursor.close();
db.close();
}
return mNewes;
}
In the above method you get and open the application database preform the query on it, anticipating any sql errors and then close the database. Doing it this way assures that you never have any resources open that you don't need/aren't using.
I've used this method in two apps that are currently out in the market and it runs rather quickly with making several hundred calls to methods I created for my stored procedures

how should I open and close my database properly

I have an app which stores some data in a SQLite DB.Also I'm doing a lot of query an requery in my app.I have about 15 activities in it.And almoust all use the DB to query for data.
But what I'm doing is opening my DB in every activity and close it in onDestroy{...} of every activity.
The problem is that onDestroy{...} may never get called and sometimes my app stays on for a long time and I switch from an activity to another opening for to many times my DB.
And sometimes I get errors like-database too many times opened and never closed.
I would try to close my DB exactly after I get my data from it and close it...moving to my next activity and re-opening and so on.....
But the problem is that in some activities I come back from other activities....closing my DB and coming back to that activity would produce a big Force Close.
What I wanna do is open my DB at the beginning of my app and close it at the end of it, but I'm facing 2 problems:
1.
Should I make my SQLiteOpenHelper class a singleton?...get an instance of it..open it in my first activity and then in my following activities just get an instance of my DB which is already opened/???
2.Where is the end of my app????How should I know where is the end of my app and where to close my DB.
EDIT:
public class DBAdapter extends SQLiteOpenHelper {
public DBAdapter(Context context) {
super(context, DATABASE_NAME, null, 1);
this.myContext = context;
}
public void openDataBase() throws SQLException {
String myPath = DATABASE_PATH + DATABASE_NAME;
db = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
}
}
That is a piece of code from my class that manages my DB.To make this singleton I should use a constructor likw this:
private DBAdapter()
{
//nothing in here
}
But this is undefined for SQLiteOpenHelper
EDIT FINAL:
This is how I did it according with zirael advice:
package com.Server_1;
import android.app.Application;
public class MyApplication extends Application{
private static DBAdapter db;
public void onCreate()
{
db=new DBAdapter(getApplicationContext());
db.createDatabase();
db.openDataBase();
}
public static DBAdapter getDatabaseAdapter()
{
return db;
}
}
In every activity I where I need DB connection I do this:
MyApplication myApplication = (MyApplication) this.getApplication();
DBAdapter db= myApplication.getDatabaseAdapter();
And finally my manifest looks like:
<application android:icon="#drawable/icon"
android:label="#string/app_name"
android:name=".MyApplication"
android:debuggable="true">
In my app I open connection to database in myApplication class (your custom class that extends Application - it should be named the same as your application in androidManifest).
AndroidManifest.xml
<application android:label="#string/app_name"
android:name="com.mypackage.MyApplication " android:debuggable="true">
MyApplication .java
public class MyApplication extends Application {
private DatabaseAdapter dbAdapter;
#Override
public void onCreate() {
dbAdapter = new DatabaseAdapter(getApplicationContext());
dbAdapter.open();
}
And in each class that need db connection I simply use:
MyApplication myApplication = (MyApplication) this.getApplication();
DatabaseAdapter dbAdapter= myApplication.getDatabaseAdapter();
MyApplication is run automatically on every application start. This way I keep only one connection to DB so it's closed when app is being removed from memory without any problem.
When you retrieve your dbAdapter from you MyApplication class, do it in a lazy fashion, creating it only when needed. In my implementation, I also open it at this time.
public static DbAdapter getDbAdapter() {
if (dbAdapter == null) {
dbAdapter = new DbAdapter();
}
dbAdapter.open();
return dbAdapter;
}
It is a good idea to use getReadableDatabase() or getWriteableDatabase() in the open method of your database adapter.
Also, I think it works better to retrieve your adapter in onStart() and close it in onStop() of the activities where it is being used, rather than using onCreate() and onDestroy().
#Override
protected void onStop() {
super.onStop();
MyApp.closeDatabase();
}
And in the MyApp class...
public static void closeDatabase() {
dbAdapter.close();
}
If you are not managing your database in line with Google's recommendations, why not - there's usually a good reason why things are the way they are...
In any case, you can use getReadableDatabase() and getWriteableDatabase() - these functions will open the database if necessary, but just return the existing database object if it is already open, thus preventing you from opening the database multiple times.
Something you might try is use a singleton that each activity would attach to in its onResume() callback, and detach from in its onPause() callback. When the detach count reaches zero, set a timer which would get canceled in the attach method. If the timer expires, close the database.
There is a good answer from another question Best place to close database connection
"According to this post by a Google engineer, there's nothing wrong with leaving the database connection open:
Android made a deliberate design decision that is can seem surprising,
to just give up on the whole idea of applications cleanly exiting and
instead let the kernel clean up their resources. After all, the kernel
needs to be able to do this anyway. Given that design, keeping
anything open for the entire duration of a process's life and never
closing it is simply not a leak. It will be cleaned up when the
process is cleaned up.
So, for simplicity, I would extend the Application class to provide a single well-defined entry point for your code, and open the database connection in its onCreate(). Store the DB connection as a field in your Application, and provide an accessor method to make the connection available to rest of your code.
Then, don't worry about closing it."

Categories

Resources