在 Android 中处理 SQLite 单例实例及其上下文依赖性

Handling SQLite singleton instances and its Context dependency in Android

我目前正在开展一个 Android 项目,该项目与 SQLite 数据库进行大量通信。我也在尝试在应用程序中实现 MVP 框架。

我目前的Singleton 实例的实现与下面类似。 (取自这个post: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);
  }
}

使用上面的现有代码,我在多个 Presenter 类 中调用 getInstance 方法,将从 Activity/Fragment 传递过来的 Context 对象传递给每个 Presenter。 Context 对象可以跨多个 类.

传递

我考虑的不是上面的代码,而是在应用程序启动时仅实例化 databaseHelper 一次,然后所有引用将指向 getInstance 方法的变体,而没有上下文依赖性。

编辑:我的主要目的是尽可能多地删除 Presenter 类 中 Context 对象的存在,从而使代码 'cleaner'。因为对 getInstance provide/inject 的所有调用都是相同类型的上下文(应用程序的上下文而不是 Activity 特定的上下文),所以我认为没有必要将上下文对象作为参数。

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);
  }
} 

我想知道的是,这种方法会有什么缺点吗?谢谢!

您正在将惰性初始化换成静态初始化。

一般来说,惰性初始化可以在应用程序的整个生命周期内分摊初始化成本。在这种情况下,它似乎不太重要,原因有二:

  1. 几乎可以肯定您会需要这个数据库。通过推迟初始化,您似乎不太可能完全避免这样做。
  2. Android 框架保证 DBHelper 构造函数可以来自 UI 线程 运行:这不是花时间的事情。花时间的事情是第一次调用 getWriteableDatabase。 Helper 的懒惰创建几乎没有完成任何事情。

您可以考虑通过像这样在应用程序中初始化数据库来使代码更简单:

public class DBDrivenApp extends Application implements DBProvider {

  // ...

  private PostsDatabaseHelper db;

  // ...

  @Override
  public void onCreate() {
    super.onCreate();
    db = new PostsDatabaseHelper(this);
  }

  @Override
  public PostsDatabaseHelper getDB() { return db; }

  // ...
}

...而且,更好的是,使用 IoC 框架(如 Dagger2)注入数据库实例,以便您可以在测试中对其进行模拟。