这是一个自我回答的问题,我想问早些时候,因为我有代表暴露问题在我的项目,但最终解决了几个小时的研究。与其保持沉默,我还以为这会对未来的人有所帮助。本教程演示如何创建Room数据库并在活动/片段中使用它。这里给出的示例用例是查询数据库的大小和更新片段中的视图。
注意:下面的代码中有一些Dagger-Hilt依赖项注入,但是如果您正在手动执行自己的依赖项注入,则应该采用相同的方法。我还希望您对MVVM体系结构有一些基本知识。如果您对涉及LiveData的其他方法感兴趣,您可能会在这里找到有用的Java相关问题:resource 1,resource 2;然而,重点是Kotlin,这个解决方案不需要LiveData。
发布于 2020-07-29 04:26:44
您必须将项目中的kotlin文件关联起来,因为项目的包是结构化的,但是导入应该保持不变。在本例中,我使用Dagger-Hilt进行依赖注入以避免样板代码。
ItemsYouAreStoringInDB.kt
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
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
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。
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
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 databaseBaseApplication.kt
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class BaseApplication : Application() {}您还需要更新AndroidManifest文件,并选择BaseApplication作为应用程序入口点<application android:name="path.to.BaseApplication" ...,以允许安卓利用Dagger。
继续..。
YourViewModel.kt
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
@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
}
}
}
}https://stackoverflow.com/questions/63146318
复制相似问题