首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建和使用Kotlin [Dagger-Hilt]中的房间数据库

如何创建和使用Kotlin [Dagger-Hilt]中的房间数据库
EN

Stack Overflow用户
提问于 2020-07-29 04:26:44
回答 1查看 14.4K关注 0票数 27

这是一个自我回答的问题,我想问早些时候,因为我有代表暴露问题在我的项目,但最终解决了几个小时的研究。与其保持沉默,我还以为这会对未来的人有所帮助。本教程演示如何创建Room数据库并在活动/片段中使用它。这里给出的示例用例是查询数据库的大小和更新片段中的视图。

注意:下面的代码中有一些Dagger-Hilt依赖项注入,但是如果您正在手动执行自己的依赖项注入,则应该采用相同的方法。我还希望您对MVVM体系结构有一些基本知识。如果您对涉及LiveData的其他方法感兴趣,您可能会在这里找到有用的Java相关问题:resource 1resource 2;然而,重点是Kotlin,这个解决方案不需要LiveData。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-29 04:26:44

您必须将项目中的kotlin文件关联起来,因为项目的包是结构化的,但是导入应该保持不变。在本例中,我使用Dagger-Hilt进行依赖注入以避免样板代码。

ItemsYouAreStoringInDB.kt

代码语言:javascript
复制
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "items")
data class ItemsYouAreStoringInDB(/*Parameter of Item entry*/) {
    @PrimaryKey(autoGenerate = true)
    var id: Int? = null
}

YourDao.kt

代码语言:javascript
复制
import androidx.room.*
@Dao
interface YourDAO {
    // Other insertion/deletion/query operations

    @Query("SELECT count(id) FROM items") // items is the table in the @Entity tag of ItemsYouAreStoringInDB.kt, id is a primary key which ensures each entry in DB is unique
    suspend fun numberOfItemsInDB() : Int // suspend keyword to run in coroutine
}

YourDatabase.kt

代码语言:javascript
复制
import androidx.room.Database
import androidx.room.RoomDatabase

@Database(
    entities = [ItemsYouAreStoringInDB::class], // Tell the database the entries will hold data of this type
    version = 1
)

abstract class YourDatabase : RoomDatabase() {

    abstract fun getYourDao(): YourDAO
}

使用Dagger-Hilt进行依赖注入,可以创建YourRepository,就像Dagger-Hilt在引擎盖下做一些事情一样,通过YourDatabase的抽象乐趣getYourDao() getYourDao()getYourDao提供notificationDao。

代码语言:javascript
复制
import path.to.ItemsYouAreStoringInDB
import path.to.YourDAO
import javax.inject.Inject // Dagger-Hilt to allow @Inject constructor

class YourRepository @Inject constructor(
    private val yourDAO: YourDAO
){
    // Other functions from YourDao.kt

    suspend fun numberOfItemsInDB() = yourDAO.numberOfItemsInDB()
}

这不是关于如何使用Dagger-Hilt的演示,但以下两个文件是必要的:

AppModule.kt

代码语言:javascript
复制
import android.content.Context
import androidx.room.Room
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.hilt.android.qualifiers.ApplicationContext
import path.to.YourDatabase

import javax.inject.Singleton


@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Singleton // Tell Dagger-Hilt to create a singleton accessible everywhere in ApplicationCompenent (i.e. everywhere in the application)
    @Provides
    fun provideYourDatabase(
        @ApplicationContext app: Context
    ) = Room.databaseBuilder(
        app,
        YourDatabase::class.java,
        "your_db_name"
    ).build() // The reason we can construct a database for the repo

    @Singleton
    @Provides
    fun provideYourDao(db: YourDatabase) = db.getYourDao() // The reason we can implement a Dao for the database

BaseApplication.kt

代码语言:javascript
复制
import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp 
class BaseApplication : Application() {}

您还需要更新AndroidManifest文件,并选择BaseApplication作为应用程序入口点<application android:name="path.to.BaseApplication" ...,以允许安卓利用Dagger。

继续..。

YourViewModel.kt

代码语言:javascript
复制
import dagger.hilt.android.lifecycle.HiltViewModel
import androidx.lifecycle.ViewModel
import path.to.YourRepository

@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: YourRepository
): ViewModel() {
    suspend fun databaseSize() : Int {
        return repository.numberOfItemsInDB()
    }
}

现在,您的视图模型可以作为单个实例在整个应用程序中创建和访问(它的两个实例都不存在),您可以在片段/活动中使用它。视图模型可以访问存储库,存储库可以通过查询Room数据库来接收信息。下面是一个示例,说明如何在片段中使用此方法:

YourFragment.kt

代码语言:javascript
复制
@AndroidEntryPoint // Dagger-Hilt requirement
class YourFragment : Fragment(R.layout.fragment_yourFragmentName) {
    private val viewModel: MainViewModel by viewModels()
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setViewsBasedOnRepo() // You might want to call this in onResume()
    }

    private fun setViewsBasedOnRepo() { 
            GlobalScope.launch(Dispatchers.Main) { // Dispatchers.Main because only the Main thread can touch UI elements. Otherwise you may wish to use Dispatchers.IO instead!
                val size  =
                    withContext(Dispatchers.Default) { viewModel.databaseSize() }
                if (size == 0) { // Do stuff based on an empty database
                    btnAddItemsToDB.visibility = View.VISIBLE
                    textViewWarnNoItemsInDB.visibility = View.VISIBLE
                    recyclerViewItems.visibility = View.INVISIBLE
                } else { // Do other stuff when database has entries of type ItemsYouAreStoringInDB
                    btnAddItemsToDB.visibility = View.INVISIBLE                
                    textViewWarnNoItemsInDB.visibility = View.INVISIBLE
                    rvNotifications.visibility = View.VISIBLE
                }
            }
    }
}
票数 72
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63146318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档