Ich würde es die ganze Zeit offen halten und es in einer Lebenszyklusmethode wie onStop
oder schließen onDestroy
. Auf diese Weise können Sie leicht überprüfen , ob die Datenbank durch den Aufruf bereits verwendet wird isDbLockedByCurrentThread
oder isDbLockedByOtherThreads
auf dem einzelnen SQLiteDatabase
Objekt jedes Mal , bevor Sie es benutzen. Dies verhindert mehrfache Manipulationen an der Datenbank und schützt Ihre Anwendung vor einem möglichen Absturz
In Ihrem Singleton haben Sie möglicherweise eine Methode wie diese, um Ihr einzelnes SQLiteOpenHelper
Objekt zu erhalten:
private SQLiteDatabase db;
private MyDBOpenHelper mySingletonHelperField;
public MyDBOpenHelper getDbHelper() {
db = mySingletonHelperField.getDatabase();//returns the already created database object in my MyDBOpenHelper class(which extends `SQLiteOpenHelper`)
while(db.isDbLockedByCurrentThread() || db.isDbLockedByOtherThreads()) {
//db is locked, keep looping
}
return mySingletonHelperField;
}
Wenn Sie also Ihr offenes Hilfsobjekt verwenden möchten, rufen Sie diese Getter-Methode auf (stellen Sie sicher, dass es einen Thread hat).
Eine andere Methode in Ihrem Singleton ist möglicherweise (JEDES MAL aufgerufen, bevor Sie versuchen, den obigen Getter aufzurufen):
public void setDbHelper(MyDBOpenHelper mySingletonHelperField) {
if(null == this.mySingletonHelperField) {
this.mySingletonHelperField = mySingletonHelperField;
this.mySingletonHelperField.setDb(this.mySingletonHelperField.getWritableDatabase());//creates and sets the database object in the MyDBOpenHelper class
}
}
Möglicherweise möchten Sie die Datenbank auch im Singleton schließen:
public void finalize() throws Throwable {
if(null != mySingletonHelperField)
mySingletonHelperField.close();
if(null != db)
db.close();
super.finalize();
}
Wenn die Benutzer Ihrer Anwendung in der Lage sind, sehr schnell viele Datenbankinteraktionen zu erstellen, sollten Sie etwas verwenden, wie ich oben gezeigt habe. Aber wenn es nur minimale Datenbankinteraktionen gibt, würde ich mir darüber keine Sorgen machen und die Datenbank jedes Mal erstellen und schließen.
Ab sofort muss nicht mehr überprüft werden, ob die Datenbank von einem anderen Thread gesperrt wurde. Während Sie Singleton SQLiteOpenHelper in jedem Thread verwenden, sind Sie sicher. Aus der
isDbLockedByCurrentThread
Dokumentation:isDbLockedByOtherThreads
ist seit API Level 16 veraltet.quelle
Zu den Fragen:
Wir sollten 'DB öffnen', 'Verbindung öffnen' teilen. SQLiteOpenHelper.getWritableDatabase () gibt eine geöffnete Datenbank an. Wir müssen jedoch keine Verbindungen steuern, da dies intern erfolgt.
Ja, so ist es. Verbindungen hängen nicht, wenn Transaktionen ordnungsgemäß geschlossen werden. Beachten Sie, dass Ihre Datenbank auch automatisch geschlossen wird, wenn GC sie abschließt.
Das Schließen der SQLiteDatabase-Instanz bietet nichts Außergewöhnliches als das Schließen von Verbindungen. Dies ist jedoch für Entwickler schlecht, wenn derzeit einige Verbindungen bestehen. Nach SQLiteDatabase.close () gibt SQLiteOpenHelper.getWritableDatabase () eine neue Instanz zurück.
Nein, gibt es nicht. Beachten Sie auch, dass das Schließen der Datenbank zu einem nicht verwandten Zeitpunkt und Thread, z. B. in Activity.onStop (), aktive Verbindungen schließen und die Daten in einem inkonsistenten Zustand belassen kann.
quelle
Android 8.1 hat eine
SQLiteOpenHelper.setIdleConnectionTimeout(long)
Methode, die:https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#setIdleConnectionTimeout(long)
quelle
Aus Sicht der Leistung besteht der optimale Weg darin, eine einzelne Instanz von SQLiteOpenHelper auf Anwendungsebene zu belassen. Das Öffnen einer Datenbank kann teuer sein und ist ein Blockierungsvorgang. Daher sollte dies nicht im Hauptthread und / oder in den Aktivitätslebenszyklusmethoden durchgeführt werden.
Die in Android 8.1 eingeführte Methode setIdleConnectionTimeout () kann verwendet werden, um RAM freizugeben, wenn die Datenbank nicht verwendet wird. Wenn das Leerlaufzeitlimit festgelegt ist, werden die Datenbankverbindungen nach einer Zeit der Inaktivität geschlossen, dh wenn nicht auf die Datenbank zugegriffen wurde. Verbindungen werden für die App transparent wieder geöffnet, wenn eine neue Abfrage ausgeführt wird.
Darüber hinaus kann eine App releaseMemory () aufrufen, wenn sie in den Hintergrund tritt oder Speicherdruck erkennt, z. B. in onTrimMemory ()
quelle
Sie können auch ContentProvider verwenden. Es wird dieses Zeug für Sie tun.
quelle
Erstellen Sie Ihren eigenen Anwendungskontext und öffnen und schließen Sie die Datenbank von dort aus. Dieses Objekt verfügt auch über eine OnTerminate () -Methode, mit der Sie die Verbindung schließen können. Ich habe es noch nicht versucht, aber es scheint ein besserer Ansatz zu sein.
@binnyb: Ich mag es nicht, finalize () zu verwenden, um die Verbindung zu schließen. Könnte funktionieren, aber nach meinem Verständnis ist das Schreiben von Code in einer Java finalize () -Methode eine schlechte Idee.
quelle
onTerminate
dies in einer Produktionsumgebung nicht aufgerufen wird - developer.android.com/reference/android/app/…