Android 如何通过视图模型、存储库和DAO从房间数据库中读取值?

Android 如何通过视图模型、存储库和DAO从房间数据库中读取值?,android,android-studio,android-sqlite,android-room,android-database,Android,Android Studio,Android Sqlite,Android Room,Android Database,我正在使用Room数据库开发一个Android应用程序。我已经学会了将值写入数据库。就读取/获取而言,我只能获得与从数据库获取整个值列表相关的帮助(并将它们填充到RecyclerView中)。但是,我不知道如何根据某些条件从数据库中获取单个值 以下是我的代码: User.kt @Entity(tableName = TABLE_NAME) data class User( @PrimaryKey(autoGenerate = true) val id: Int = 0,

我正在使用Room数据库开发一个Android应用程序。我已经学会了将值写入数据库。就读取/获取而言,我只能获得与从数据库获取整个值列表相关的帮助(并将它们填充到RecyclerView中)。但是,我不知道如何根据某些条件从数据库中获取单个值

以下是我的代码:

User.kt

@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
)
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")
    }
}
class UserRepository(private val userDAO: UserDAO) {
      
     val allUsers: Flow<List<User>> = userDAO.getAll()

     @Suppress("RedundantSuspendModifier")
     @WorkerThread
     suspend fun insert(user: User) {
          userDAO.insert(user)
     }
}
@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"
    }
}
@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
            }
        }
    }
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()) }
}
class LoginActivity : AppCompatActivity() {

    private val userViewModel: UserViewModel by viewModels {
        UserViewModelFactory((application as MyApplication).userRepository)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        btnLogin.setOnClickListener {
            val email=editEmail.text.toString()
            val password=editPassword.text.toString()
           
            /**
             * code to check whether user with this email and password exists or not
             */
        }
    }
}
我们从UserDAO获得
表名

UserViewModel.kt

@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
)
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")
    }
}
class UserRepository(private val userDAO: UserDAO) {
      
     val allUsers: Flow<List<User>> = userDAO.getAll()

     @Suppress("RedundantSuspendModifier")
     @WorkerThread
     suspend fun insert(user: User) {
          userDAO.insert(user)
     }
}
@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"
    }
}
@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
            }
        }
    }
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()) }
}
class LoginActivity : AppCompatActivity() {

    private val userViewModel: UserViewModel by viewModels {
        UserViewModelFactory((application as MyApplication).userRepository)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        btnLogin.setOnClickListener {
            val email=editEmail.text.toString()
            val password=editPassword.text.toString()
           
            /**
             * code to check whether user with this email and password exists or not
             */
        }
    }
}
MyApplication.kt

@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
)
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")
    }
}
class UserRepository(private val userDAO: UserDAO) {
      
     val allUsers: Flow<List<User>> = userDAO.getAll()

     @Suppress("RedundantSuspendModifier")
     @WorkerThread
     suspend fun insert(user: User) {
          userDAO.insert(user)
     }
}
@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"
    }
}
@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
            }
        }
    }
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()) }
}
class LoginActivity : AppCompatActivity() {

    private val userViewModel: UserViewModel by viewModels {
        UserViewModelFactory((application as MyApplication).userRepository)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        btnLogin.setOnClickListener {
            val email=editEmail.text.toString()
            val password=editPassword.text.toString()
           
            /**
             * code to check whether user with this email and password exists or not
             */
        }
    }
}
现在,我想创建一个登录活动,并尝试根据电子邮件和密码登录用户

LoginActivity.kt

@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
)
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")
    }
}
class UserRepository(private val userDAO: UserDAO) {
      
     val allUsers: Flow<List<User>> = userDAO.getAll()

     @Suppress("RedundantSuspendModifier")
     @WorkerThread
     suspend fun insert(user: User) {
          userDAO.insert(user)
     }
}
@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"
    }
}
@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
            }
        }
    }
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()) }
}
class LoginActivity : AppCompatActivity() {

    private val userViewModel: UserViewModel by viewModels {
        UserViewModelFactory((application as MyApplication).userRepository)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        btnLogin.setOnClickListener {
            val email=editEmail.text.toString()
            val password=editPassword.text.toString()
           
            /**
             * code to check whether user with this email and password exists or not
             */
        }
    }
}

我不知道如何获取具有匹配电子邮件和密码的用户请帮助我。

您必须在DAO中创建函数才能做到这一点,与您创建的函数类似

@Query("SELECT * FROM " + TABLE_NAME)
fun getAll(): Flow<List<User>>
@Query(“选择*自”+表名)
fun getAll():流

请参阅示例并了解有关

的更多信息。您可以在
UserDao
中添加一个方法,该方法将获取用户的记录(如果可用),如下所示

@Query("SELECT * FROM " + TABLE_NAME + " WHERE email = :email AND password = :password LIMIT 1")
fun isValidUser(email: String, password: String): Flow<User?>
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)
 }
    
}

谢谢你的回答。我在UserViewModel中得到了“未解决的引用:收集”。不用担心。我解决了这个问题。1.
repository.isValiduser(user(name=”,email=email,password=password
2.
userLiveData.postValue(it)
无法访问“postValue”:它在“LiveData”中受保护。我通过替换
val userLiveData:LiveData=MutableLiveData()解决了这个问题
带有
val userLiveData=MutableLiveData()