当前位置: 首页 > 知识库问答 >
问题:

Android Room-避免将上下文传递给Singleton

宦正诚
2023-03-14

我正在尝试将一个项目迁移到Android Room。阅读了Android Room文档后,我注意到Singleton适合访问我的数据库。

Android开发者的报价:

注意:如果您的应用程序在单个进程中运行,则在实例化AppDatabase对象时应遵循单例设计模式。每个RoomDatabase实例都相当昂贵,您很少需要在单个进程中访问多个实例。

我编写了以下代码

@Database(entities = {Category.class, News.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {

    private static final String DB_NAME = "database.db";
    private static AppDatabase instance;

    public abstract CategoryDao categoryDao();
    public abstract NewsDao newsDao();

    private AppDatabase () {}

    public static AppDatabase getInstance(Context context) {
        if (instance == null) {
            synchronized (AppDatabase.class) {
                if (instance == null) {
                    instance = Room.databaseBuilder(context.getApplicationContext(),
                            AppDatabase.class, DB_NAME).build();
                }
            }
        }
        return instance;
    }
}

只是一个简单的双重检查锁定单例。

我读过一些指南/教程,几乎每个人都有类似的方法,但是我可以看到这种方法的一些问题:

  • 每次都需要传递Context,即使您只需要一次来初始化Singleton。
  • 如果我需要在没有Context可用的情况下访问数据库怎么办?
  • 甚至可以将参数发送给单例?

有什么想法如何实现解决这些问题的房间数据库单例?

如果可能的话,我希望避免像Dagger2这样的DI库。

共有3个答案

劳昊明
2023-03-14
@Database(entities = {Category.class, News.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {

   private static final String DB_NAME = "database.db";
   private static AppDatabase instance;
   public abstract CategoryDao categoryDao();
   public abstract NewsDao newsDao();

   private AppDatabase () {}

   // Use this to call on any place
   public static AppDatabase getInstance() {
      return instance;
   }
   // Use once to Create and setup the object
   public static AppDatabase setInstance(Context context) {
      if (instance == null) {
         synchronized (AppDatabase.class) {
            if (instance == null) {
                instance = Room.databaseBuilder(context.getApplicationContext(),
                        AppDatabase.class, DB_NAME).build();
            }
        }
     }
     return instance;
   }
}

// Second you need to set instance on Application Class which create and make your DB 
  //Ready for Use Before anything perform
public class MyApplication extends Application {
   @Override
   public void onCreate() {
      super.onCreate();
      AppDatabase.setInstance(this)
   }
}

使用

//Need to call
AppDatabase.getInstance().categoryDao();
莫河
2023-03-14

您可以实例化数据库,然后锁定实例。

此外,调用上下文。applicationContext返回当前进程的单个全局应用程序对象的上下文。此上下文的生命周期与当前上下文相分离,当前上下文与进程的生命周期而不是当前组件相关联。

/**
 * The Room Database that contains the item table.
 */
@Database(entities = arrayOf(Item::class), version = 1, exportSchema = false)
abstract class ItemDb : RoomDatabase() {
    abstract fun itemDao(): ItemDao

    companion object {
        private var INSTANCE: ItemDb? = null

        private val lock = Any()

        @JvmStatic
        fun getInstance(context: Context): ItemDb {

            // When calling this instance concurrently from multiple threads we're in serious trouble:
            // So we use this method, 'synchronized' to lock the instance
            synchronized(lock) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.applicationContext, ItemDb::class.java, "items.db").build()
                }
                return INSTANCE!!
            }
        }
    }
}
国言
2023-03-14

您可以初始化数据库并将其实例保存在应用程序类中,如下所示。

public class MyApplication extends Application {

    public AppDatabase database;

    @Override
    public void onCreate() {
        super.onCreate();

        database = AppDatabase.getInstance(this)
    }
}

稍后,您可以使用以下工具访问您的参考信息:

((MyApplication)activity).database

希望这会有所帮助。

 类似资料:
  • 在开发新产品时,我创建了一个后端和前端项目。对于前端,我使用带有Typescript的角度框架。下面是一个问题,因为我对这门语言还不熟悉(几天前)。我的问题是关于回调以及如何避免“this”上下文中的显式传递。我已经阅读了一些资源,我将链接它们。 下面我将为HttpClient实现一个包装器。快速版本是使用插件架构(由角度路由支持)的模块进行流控制,最好是通过使用观察员和订阅者广播401之类的错误

  • 问题内容: 上周受本文启发,我正在重构我必须更明确地将上下文(数据库池,会话存储等)传递给处理程序的应用程序。 但是,我遇到的一个问题是,如果没有全局模板映射,我的自定义处理程序类型(要满足)上的方法将无法再访问该映射以呈现模板。 我需要保留全局变量,或者将我的自定义处理程序类型重新定义为结构。 有没有更好的方法来实现这一目标? func.go struct.go 有没有更干净的方法将实例传递给?

  • 问题内容: 我以为这是我可以轻松搜索的东西,但也许我没有问正确的问题… 如何在给定的javascript函数中设置“ this”所指的内容? 例如,与大多数jQuery函数一样,例如: 如何编写/调用自己的独立函数,并在调用时具有适当的“ this”引用?我使用jQuery,因此,如果有jQuery特定的方式可以做到,那将是理想的选择。 问题答案: Javascript 和方法允许您设置函数的 上

  • 问题内容: 如何传递上下文?我想打电话,如果在1000毫秒。我怎样才能做到这一点? 当我尝试上述操作时,指的是窗口。 问题答案: 编辑: 总而言之,早在2010年,当有人问这个问题时,解决此问题的最常用方法是保存对进行函数调用的上下文的引用,因为执行函数时要指向全局对象: 在一年前发布的ES5规范中,它引入了该方法,但最初的答案中并未建议使用该方法,因为该方法尚未得到广泛支持,您需要使用polyf

  • 问题内容: 这个问题一定很明显,但我不知道。 在模板中,我链接到媒体目录中的js文件。从该文件中,我想访问一个{{my_chart}}之类的上下文变量。 问题答案: 我认为这样不可能。如果要访问视图提供的某些数据,则必须将其传递给js函数。 例 js文件: 视图 希望这可以帮助 :)