0

In some passages, I had the error of sqllite "open connection already open" ... ok, actually I was not busy to always close the connection since I had read that it was advisable not to do it if the operations were not massive ... but obviously it is not always true ... or not? I am confused at this point ....

To solve this problem I inserted this code in every activity that does database operations with its adapter:

@Override
protected void onDestroy ()
{
super.onDestroy ();
mDbHelper.closeConnection ();
}

This has solved everything and everything has worked for months.

Now implementing other I receive this error:

"attempt to reopen already closed object then database closed"

An 'Activity calls via OnActivityForResult another activity but "someone or something" (I assume low-level android) calls my "OnDestroy" (going to close the connection) ... the reason that triggers the error I have found but I have no idea how to intervene ... I'm not the one to call OnDestroy but Android ... how does it come out?

For now (in my case of the activity that calls the other) I have circumvented the problem like this:

@Override
protected void onDestroy ()
{
if (! m_Modality.equalsIgnoreCase ("MYCALLBACK"))
{
mDbHelper.closeConnection ();
}
}

But I do not like it and I would like to understand once and for all how the hell you have to work on this sqlite ...

  • If I do not have to close the connection because of messages about whether it is already open?

  • If I close it because then by messages saying that it has just been closed?

  • If ANDROID call the methods where I insert the closure of the connection as I can never manage things in a definitive way?

I hope someone can clarify my ideas ...

Bronz
  • 217
  • 3
  • 7
  • Do you have Cursor's? if you close a database and you try to access a cursor then you will get such a message. Personally I rarely close a database except in the main activities `onDestroy`. This may be of interest [Android SQLite DB When to Close](https://stackoverflow.com/questions/4557154/android-sqlite-db-when-to-close) – MikeT Jan 19 '18 at 06:04
  • The problem is just this ... onDestroy () can be called by the operating system (Android) at its discretion (if it requires resources) ... at that point you find yourself with the connection closed and if you try to reopen it immediately you see the error message! .... you find yourself in a vicious circle. :-) – Bronz Jan 21 '18 at 02:46

2 Answers2

0

I'd suggest not trying to close connections/database, as opening a database is resource expensive (see quotes below) and often unecesssary. Rather perhaps just close it in the main activities onDestroy, perhaps in conjunction with using a singleton for the SQLiteDatabase/connection.

Cursors though should always be closed when they are done with, too many open will result in an exception. I follow the rule, if they are used solely within a method then close within the method. If they are used by an activity's UI (e.g. Spinner, ListView etc) close the cursor(s) in the activity's onDestroy. If they are created within loops then close them immediately when done with them.

Since getWritableDatabase() and getReadableDatabase() are expensive to call when the database is closed, you should leave your database connection open for as long as you possibly need to access it. Typically, it is optimal to close the database in the onDestroy() of the calling Activity. Persisting Database Connection

and

Closing the connection throws away the page cache, and requires that the schema version is checked and the entire schema is re-parsed the next time it is opened.

In most apps, there are not enough database accesses so that the overhead of continually re-opening the database would actually become noticeable. But this is no reason to add useless code to your app.

Please note that the SQLiteDatabase object is reference counted. So if you are using a global open helper instance, you can keep the DB open with an extra getWritableDatabase() call, even when all your other code calls close(). CL's answer

You may also wish to read Using Singleton design pattern for SQLiteDatabase

MikeT
  • 51,415
  • 16
  • 49
  • 68
0

In some case, for example wend you pass a cursor result in another function is not possible close the cursor (you must pass a cursor not null) , i try always to create a 'read' o 'filter' template function and in Finally i close the cursor but not in all...this is impossible for all case...this depend for my stack cycle, different for any case,it's a big app, 30 sqliteadapter interaction...i think that it's a error forced a developer to close and open always in different mode;way sqlite generate a error if i open and re-closed a connection...memory?...it's a hell in a complex app....i read your link information, for now thanks!

This is my code: (I have a interface custom base but not important)

@Override
    public Cursor fetchFiltro(String filtroWhere) {
        Cursor mycursor =null;
        try {
            openConnection();
            mycursor = getDatabase().query(true, getNomeTab(),
                    new String[]  { COL_ID, COL_CODICE, COL_DESCRIZIONE,COL_PREZZOACQ,COL_PREZZOVEN, COL_CODICEUMISURA, COL_CODICEUMISURACONF, COL_QTA, COL_CODICECATEGORIA,COL_CODICEIVA,  COL_FORNITORE,  COL_CODICEFORNITORE, COL_ORDINEMINIMO,
                COL_DATAINSERIMENTO},   
                filtroWhere, null, null, null, COL_DATAINSERIMENTO +" desc", null );

            return mycursor;
        }
        catch (Exception e) 
        {
            Toast.makeText(MyApp.getContext(), e.getMessage(),Toast.LENGTH_LONG).show();
            UtiLog.WriteLogOnTop(mClassName + ".fetchFiltro() " +   e.getMessage().toString(),UtiLog.ERROR);
            if (!(mycursor==null)) {mycursor.close();}
            return null;
        }

        finally 
        {

        }
    }

I call from:

public List<Articolo>  dammiListaArticoliDaSqlWhere( String prm_sqlWhere  ) 
{

    List<Articolo> listaArticoli= new ArrayList<Articolo>();

    Cursor cursor = fetchFiltro(prm_sqlWhere);
    if( cursor != null )
    {
        while ( cursor.moveToNext() ) 
        {
            Articolo articolo = getArticolo(cursor);
            listaArticoli.add( articolo );
        } 
        cursor.close();
    }
    return listaArticoli;   
}

My Openconnection() call in dbHelper class function:

public void openConnection() throws SQLException 
    {
        dbHelper.openConnection();
    }

The code of OpenConnection:

public void openConnection() throws SQLException 
    {
        if (getDatabase()==null)
        {
            setDatabase( getWritableDatabase() );       
        }
    }

  private void setDatabase(SQLiteDatabase database) 
    {
    this.database = database;
    }

It works perfectly ... it has problems only when the operating system (of its own initiative) calls the OnDestroy of the activities (where I had to insert the closeconnection ()) ... I can not remove that closeconnection (), if I remove it in other activities it gives me the message "database already open" .... I can not get out of this situation, I'm always forced to put pieces of code to the thing manually, from case to case, it's frustrating. Thanks again

Bronz
  • 217
  • 3
  • 7