Ich arbeite derzeit an einem Android-Projekt, das eine Menge Kommunikation mit der SQLite-Datenbank durchführt. Ich versuche auch, ein MVP-Framework innerhalb der App zu implementieren.Umgang mit SQLite Singleton-Instanzen und ihre Kontextabhängigkeit in Android
Meine aktuelle Implementierung der Singleton-Instanz ähnelt der folgenden. (Von diesem Posten genommen: https://github.com/codepath/android_guides/wiki/Local-Databases-with-SQLiteOpenHelper)
public class PostsDatabaseHelper extends SQLiteOpenHelper {
private static PostsDatabaseHelper sInstance;
public static synchronized PostsDatabaseHelper getInstance(Context context) {
if (sInstance == null) {
sInstance = new PostsDatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
private PostsDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
Mit dem vorhandenen Code oben, ich nenne die getInstance Methode in mehreren Presenter Klassen, in jedem von ihnen das Context-Objekt, das auf der Aktivität/Fragment übergeben wurde. Die Context-Objekte können über mehrere Klassen hinweg übergeben werden.
Anstelle des obigen Codes dachte ich daran, den databaseHelper nur einmal zu Beginn der Anwendung zu instanziieren, und dann verweisen alle Referenzen auf eine Variante der getInstance-Methode ohne die Kontextabhängigkeit.
BEARBEITEN: Mein Hauptziel ist es, so weit wie möglich das Vorhandensein des Context-Objekts in den Presenter-Klassen zu entfernen, um den Code "sauberer" zu machen. Da alle Aufrufe von getInstance den gleichen Kontexttyp (den Kontext der Anwendung und keinen aktivitätsspezifischen Kontext) bereitstellen/einfügen, wird das Kontextobjekt nicht als Argument angezeigt.
public class PostsDatabaseHelper extends SQLiteOpenHelper {
private static PostsDatabaseHelper sInstance;
// called by all other classes
public static synchronized PostsDatabaseHelper getInstance() {
if (sInstance == null) {
//throw error
}
return sInstance;
}
// only called once at the start of the Application
public static void instantiateInstance(Context context){
sInstance = new PostsDatabaseHelper(context.getApplicationContext());
}
private PostsDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
Was ich gerne wissen würde, ist, gibt es irgendwelche Nachteile für diesen Ansatz? Vielen Dank!
Hallo Blake, danke für die ausführliche Antwort. Ich stimme Ihnen zu, dass der Aufwand für die Initialisierung vernachlässigbar ist, wenn Sie die lazy-Initialisierung verwenden. Mein Hauptziel ist es, das Vorhandensein des 'Context'-Objekts in den Presenter-Klassen wirklich zu reduzieren, um den Code' sauberer 'zu machen. Da alle Aufrufe der Methode getInstance tatsächlich denselben Anwendungskontext bereitstellen, sehe ich keinen Grund, warum das Context-Objekt überhaupt als Argument für nachfolgende Aufrufe übergeben werden sollte. Wenn das Context-Objekt, das übergeben wurde, ein aktivitätsspezifischer Kontext ist, ist es sinnvoll, es als Argument zu verwenden. –
Ja. Ich denke, ich stimme all dem zu. Wenn Sie den von mir vorgeschlagenen Code verwenden, müssen Sie den DBProvider an Ihren Presenter übergeben (was übrigens ein Kontext und eine Anwendung ist). Wenn dein Presenter Sachen von der DB bekommen muss, scheint das vernünftig ... –
...oder, btw, wenn das zu alt für dich ist, könntest du etwas mehr iOS-Stil machen, indem du den DBHelper in etwas einwickelst, das auf einem Event-Bus horcht. Dann müssten Sie den DBProvider nicht einmal an den Presenter übergeben. –