这是一个自我回答的问题,我想在早些时候问这个问题,因为我的项目中存在代表曝光问题,但经过几个小时的研究,最终还是解决了这个问题。与其保持沉默,我想这可能会对将来的人有所帮助。本教程演示了如何创建Room数据库并在活动/片段中使用它。这里给出的示例用例是查询数据库的大小并更新片段中的视图。
注意:下面的代码中有一些 Dagger-Hilt 依赖项注入,但如果您手动执行自己的依赖项注入,则应应用相同的方法。我还希望您有一些关于 MVVM 架构的基本知识。如果您对涉及 LiveData 的其他方法感兴趣,您可以在此处找到有用的 Java 相关问题:资源 1、资源 2;但是,重点是 Kotlin,此解决方案不需要 LiveData。
您必须将项目中的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
}
你的道
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
}
您的数据库.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()YourRepocitory.kt提供通知Dao
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的演示,但需要以下两个文件:
应用模块.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 database
BaseApplication.kt
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class BaseApplication : Application() {}
您还需要更新Android清单文件并选择基础应用程序作为应用程序切入点
继续…
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()
}
}
现在您的视图模型可以创建,并且可以在整个应用程序中作为单例访问(不能存在它的两个实例),您可以在片段/活动中使用它。视图模型可以访问存储库,该存储库可以通过查询房间数据库接收信息。以下是如何在片段中使用它的示例:
你的片段.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
}
}
}
}
在第一次创建房间数据库时,我不断遇到这种异常 这是我的房间数据库代码: 还有格雷德尔密码: 在构建项目时,我也会遇到这样的错误: 原因可能是什么?我在这里看到过类似的问题,但没有任何线索。请帮忙! 使现代化在我的刀中,我得到了这个错误 那么,如何让@Query理解它,我给它一个java字符串,而不是Kotlin字符串 另请参阅stackTrack: 查看类似的问题: 使用Room with kot
我转换java代码到kotlin代码,我得到类型未解决的java类错误。 我的Java类是 已转换的Kotlin类 非常感谢。
我是Android开发新手,需要为大学建立我的第一个项目。大学用的是旧版本的XML和Java,但是我想学Compose,所以我学了Kotlin。 现在,在设置好一切之后,我试图使用hiltViewModel()方法将视图模型注入到可组合函数中,但我得到了一个错误。我看了这个教程:https://www.youtube.com/watch?v=A7CGcFjQQtQ 在让这个工作之后。现在它说找不到
我尝试在Android房间中附加数据库,如下所示:如何从Android房间中的多个数据库中进行选择(如何附加数据库),但在构建项目时出现错误:错误:查询有问题:[SQLITE\u错误]SQL错误或缺少数据库(没有这样的表:database.table)错误 当我添加@SkipQuery验证时,错误发生了变化:错误:不确定如何将游标转换为此方法的返回类型。 当我从查询中删除“myDatabase.”
我正在使用更新动作栏中的标题 共享视图模型 主要活动观察者 使用下面的代码似乎会在< code>Fragment中创建新的实例(在调试器中检查): 但似乎是这样的 文章参考 这是应该这样做还是我做错了什么? 谢谢你!
我正在使用Room作为应用程序的数据库。我正在用改型从服务器上获取数据。场景是,我有一个名为Photo的类,并用实体进行注释,以供room使用,我使用这个类使用retroft映射API的响应。我需要使用同一个类创建两个表,例如:最新的照片表和流行的照片表。我怎样才能做到这一点。 > 我不想创建一个新的类并使它从另一个类扩展 我有一个想法,通过插入一个新的列,表明照片是流行的或最新的,但我不知道如何