热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在kotlin中使用房间作为单身人士

如何解决《在kotlin中使用房间作为单身人士》经验,为你挑选了2个好方法。

我正在尝试使用Room作为单身人士,所以我不必再调用Room.databaseBuilder()- 这是昂贵的 - 不止一次.

@Database(entities = arrayOf(
        Price::class,
        StationOrder::class,
        TicketPrice::class,
        Train::class,
        TrainCategory::class
), version = 2)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {

    abstract fun dao(): TrainDao

companion object {
        fun createDatabase(context: Context): AppDatabase
                = Room.databaseBuilder(context, AppDatabase::class.java, "trains.db").build()
    }
}

注意:

    无法使用Object,因为Room需要使用abstract class.

    单例必须是线程安全的,因为多个线程可能同时访问它.

    必须能够Context作为一个论点.


我查看了所有类似的StackOverflow问题,但没有一个满足我的要求

在Kotlin中使用参数的Singleton 不是线程安全的

Kotlin - 在Android中转换Singleton DatabaseController的最佳方法 不是线程安全的

Kotlin线程使用参数 使用对象保存本机惰性单例



1> humazed..:

我找到了解决方案,所以这是将来我和任何可能遇到相同问题的人的答案。


经过研究,我发现我有两个选择。

    使用双重检查锁定

    使用按需初始化持有人惯用语

所以我考虑实现其中之一,但这在kotlin中感觉不对,因为样板代码太多了:p


因此,在进行了更多研究之后,我偶然发现了这篇出色的文章,该文章提供了一种出色的解决方案,该解决方案使用有效的方式使用了双重检查锁定。

我的代码变成这样:

companion object : SingletonHolder({
       Room.databaseBuilder(it, AppDatabase::class.java, "train.db").build()
})

从文章:

可重用的Kotlin实现:

我们可以封装逻辑以懒散地创建和初始化带有SingletonHolder类内部参数的单例 。为了使该逻辑线程安全,我们需要实现一种同步算法,而最有效的算法是“双重检查锁定算法”,这也是最难解决的问题。

open class SingletonHolder(creator: (A) -> T) {
    private var creator: ((A) -> T)? = creator
    @Volatile private var instance: T? = null

    fun getInstance(arg: A): T {
        val i = instance
        if (i != null) {
            return i
        }

        return synchronized(this) {
            val i2 = instance
            if (i2 != null) {
                i2
            } else {
                val created = creator!!(arg)
                instance = created
                creator = null
                created
            }
        }
    }
}

额外: 如果您要让Singleton有两个参数

open class SingletonHolder2(creator: (A, B) -> T) {
    private var creator: ((A, B) -> T)? = creator
    @Volatile private var instance: T? = null

    fun getInstance(arg0: A, arg1: B): T {
        val i = instance
        if (i != null) return i

        return synchronized(this) {
            val i2 = instance
            if (i2 != null) {
                i2
            } else {
                val created = creator!!(arg0, arg1)
                instance = created
                creator = null
                created
            }
        }
    }
}



2> Jan Slominsk..:

在这种特殊情况下我会诉诸使用匕首2,或其他一些依赖注入库像孝允或牙签。所有这三个库都允许以单例形式提供依赖关系。

这是Dagger 2模块的代码:

@Module
class AppModule constructor(private val context: Context) {
    @Provides
    @Singleton
    fun providesDatabase(): AppDatabase {
        return Room.databaseBuilder(
                context,
                AppDatabase::class.java,
                "train.db")
                .build()
    }
}

AppComponent:

@Singleton
@Component(modules = arrayOf(
        AppModule::class
))
interface AppComponent {
    fun inject(viewModel: YourViewModel)
    fun inject(repository: YourRepository)
}

提供注入的应用程序类:

class App : Application() {
    companion object {
        private lateinit var appComponent: AppComponent
        val component: AppComponent get() = appComponent
    }

    override fun onCreate() {
        super.onCreate()
        initializeDagger()
    }

    private fun initializeDagger() {
        compOnent= DaggerAppComponent.builder()
                .appModule(AppModule(this))
                .build()
    }
}

然后将数据库作为单例注入到您需要的任何位置(例如,在应用程序的存储库中):

@Inject lateinit var appDatabase: AppDatabase

init {
    App.component.inject(this)
}


推荐阅读
author-avatar
J品1北京天7W乐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有