微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过 View Model、Repository 和 DAO 从 Room 数据库读取值?

如何解决如何通过 View Model、Repository 和 DAO 从 Room 数据库读取值?

我正在使用 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>>

查看 this 示例并了解更多关于 SQL

,

您可以在 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
     }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。