9

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">
   
Community
  • 1
  • 1
adrian
  • 4,574
  • 17
  • 68
  • 119
  • This is a very good question, and I never solved it properly in my own app. I basically do what you suggest in point 1, but I never managed to implement point 2. Instead I added an option to kill the app. This seems to work OK, but it is not in line with Android guidelines. – Philip Sheard Jun 15 '11 at 10:27
  • Well, the problem is that sometimes I get "leak found"....and the way I'm managing my DB is really not in line with Android guidelines...is opened for too many times.Could u post a little bit of code to show how you did point 1...how u made it singleton...how u opened in the first activity and what u did in the other activities.Would help me a lot.Thanks:) – adrian Jun 15 '11 at 10:32

5 Answers5

9

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.

zirael
  • 1,137
  • 10
  • 21
  • So u are saying that I should make a special class that extends Application and I should open my DB there and in other every activity do what u did?I got it right?Thx – adrian Jun 15 '11 at 11:53
  • It's what I did. MyApplication class acts like singleton and is automatically handled by android (just be sure it's named correctly). – zirael Jun 15 '11 at 11:56
  • Yeah, but I editet my post so it's MyApplication. In this case it should be named MyApplication and put in com.yourcompany.utils package – zirael Jun 15 '11 at 11:58
  • Forgive me for asking....but I'm still new to this: I should put my class MyApplication in a different package called com.Anything.utils and import that package in every activity that I need connection to my DB?Thanks:) – adrian Jun 15 '11 at 12:04
  • Those are first lines from my AndroidManifest. In this case you have to put class MyApp.java in pl.mycompany.myapp.utils package and everywhere you use MyApp eclipse will remind you to import this class. – zirael Jun 15 '11 at 12:39
  • Well, it seems to be working.One last question before I accept u answer:MyApplication will be called everytime I start my app????And will be destroyed when my app shuts down and then my Db will be closed? – adrian Jun 15 '11 at 13:16
  • 1
    If we click the app many times, does the database open many times? it is only closed when the app is removed? so is it bad practice? Please explain to me. – emeraldhieu Jul 09 '11 at 20:27
  • 2
    Is the database closed automatically once the application is killed? – Todd Davies Oct 21 '12 at 16:13
3

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();
}
Thomas Williams
  • 621
  • 5
  • 15
  • What do u mean by lazy fashion? The idea is that I never close my DB.MyApplication gets called when I start my app and in onCreate() I open my DB...and then that DB I have it in all my activities:) where I need them.What is wrong???I don't need to use onDestroy() cause I open it only once at the begginning of my app!!!Isn't that the way it goes? – adrian Jun 15 '11 at 16:35
  • @george: I was actually referring to the activity where the adapter is being used rather than the application class. In your OP, you mentioned you were closing in onDestroy() of every activity. – Thomas Williams Jun 15 '11 at 18:25
2

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.

RivieraKid
  • 5,923
  • 4
  • 38
  • 47
0

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."

0

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.

mah
  • 39,056
  • 9
  • 76
  • 93