问题描述
我正在使用 Room 数据库开发 Android 应用。我已经学会了将值写入数据库。就读取/获取而言,我只能获得与从数据库中获取整个值列表(并在 RecyclerView 中填充它们)相关的帮助。但是,我不知道如何根据某些条件从数据库中获取单个值。
以下是我的代码:
User.kt
AsCollection
我们从 UserDAO 获得 @Entity(tableName = TABLE_NAME)
data class User(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,@ColumnInfo(name = "name") val name: String,@ColumnInfo(name = "email") val email: String,@ColumnInfo(name = "password") val password: String
)
。
Userviewmodel.kt
TABLE_NAME
UserRepository.kt
class Userviewmodel(private val repository: UserRepository) : viewmodel() {
val allUsers: LiveData<List<User>> = repository.allUsers.asLiveData()
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insert(user: User) = viewmodelScope.launch {
repository.insert(user)
}
}
class UserviewmodelFactory(private val repository: UserRepository) :
viewmodelProvider.Factory {
override fun <T : viewmodel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(Userviewmodel::class.java)) {
@Suppress("UNCHECKED_CAST")
return Userviewmodel(repository) as T
}
throw IllegalArgumentException("UnkNown viewmodel class")
}
}
UserDAO.kt
class UserRepository(private val userDAO: UserDAO) {
val allUsers: Flow<List<User>> = userDAO.getAll()
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(user: User) {
userDAO.insert(user)
}
}
UserDatabase.kt
@Dao
interface UserDAO {
@Query("SELECT * FROM " + TABLE_NAME)
fun getAll(): Flow<List<User>>
@Insert(onConflict = OnConflictStrategy.IGnorE)
suspend fun insert(user: User)
@Insert
fun insertAll(vararg users: User)
@Delete
fun delete(user: User)
@Query("DELETE FROM " + TABLE_NAME)
suspend fun deleteall()
companion object {
const val TABLE_NAME: String = "user_table"
}
}
MyApplication.kt
@Database(entities = arrayOf(User::class),version = 1,exportSchema = false)
public abstract class UserDatabase : RoomDatabase() {
abstract fun userDAO(): UserDAO
private class UserDatabaseCallback(private val scope: Coroutinescope) :
RoomDatabase.Callback() {
override fun onCreate(db: SupportsqliteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
scope.launch {
populateUsers(database.userDAO())
}
}
}
suspend fun populateUsers(userDAO: UserDAO) {
userDAO.deleteall()
var user = User(name = "Admin",email = "admin@example.com",password = "admin123")
userDAO.insert(user)
}
}
companion object {
/**
* Singleton prevents multiple instances of database opening at the same time
*/
@Volatile
private var INSTANCE: UserDatabase? = null
fun getDatabase(context: Context,scope: Coroutinescope): UserDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,UserDatabase::class.java,"user_database"
).addCallback(UserDatabaseCallback(scope))
.build()
INSTANCE = instance
instance // return instance
}
}
}
现在,我想创建一个登录活动并尝试根据电子邮件和密码登录用户。
LoginActivity.kt
class MyApplication : Application() {
val applicationScope = Coroutinescope(SupervisorJob())
// Using by lazy so the database and the repository are only created
// when they're needed rather than when the application starts
val database by lazy { UserDatabase.getDatabase(this,applicationScope) }
val userRepository by lazy { UserRepository(database.userDAO()) }
}
我不知道如何使用匹配的电子邮件和密码获取用户。 请帮我解决这个问题。
解决方法
你必须在 DAO 中创建函数才能做到这一点,就像你创建的那样。
@Query("SELECT * FROM " + TABLE_NAME)
fun getAll(): Flow<List<User>>
,
您可以在 UserDao
中添加一个方法,如果可用,它将获取用户的记录,如下所示
@Query("SELECT * FROM " + TABLE_NAME + " WHERE email = :email AND password = :password LIMIT 1")
fun isValidUser(email: String,password: String): Flow<User?>
然后在存储库中添加一个方法来验证获取的用户是否为空
@WorkerThread
suspend fun isValidUser(user: User): Flow<User?> {
return userDAO.isValidUser(user.email,user.password)
}
然后在 ViewModel 中,再添加一个如下所示的方法
val userLiveData: LiveData<User?> = MutableLiveData()
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insert(user: User) = viewModelScope.launch {
repository.insert(user)
}
fun validateUser(email: String,password: String)= viewModelScope.launch{
repository.isValiduser(user(name = "",email = email,password = password
).collect{
userLiveData.postValue(it)
}
}
最后,在活动中
btnLogin.setOnClickListener {
val email=editEmail.text.toString()
val password=editPassword.text.toString()
userViewModel.validateUser(email,password)
}
userViewModel.userLiveData.observe(this){
if(it != null){
//valid user
}else{
//invalid
}
}