Android室 - 试图根据主ID查询单行

发布于 2025-02-06 12:29:42 字数 2974 浏览 2 评论 0 原文

我想实现什么?

获取具有我需要的ID的单一数据。 的SQL等效从最爱中选择 * link ='link'。我写了一个名为getOnefav()的乐趣。我正在关注教程

到目前为止我设置了什么?

实体

@Entity(tableName = "favs")
data class Favorite(
    @PrimaryKey @ColumnInfo(name = "link") val link : String,
    @ColumnInfo(name = "keywords") val keywords : String
)

dao

@Dao
interface FavDAO {
    @Query("SELECT * FROM favs")
    fun getAllFavsLive(): Flow<List<Favorite>>

    @Query("SELECT * FROM favs WHERE link = :link")
    fun getOneFav(link: String): Favorite

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(link: Favorite)
}

存储库

class FavRepo (private val favDao: FavDAO) {

    val allFavs: Flow<List<Favorite>> = favDao.getAllFavsLive()

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun insert(link: Favorite) {
        favDao.insert(link)
    }

    fun getOneFav(link: String) = favDao.getOneFav(link)

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun delete(link: String) {
        favDao.delete(link)
    }
}

ViewModel

class FavViewModel (private val repository: FavRepo) : ViewModel() {

    val allFavs: LiveData<List<Favorite>> = repository.allFavs.asLiveData()

    fun insert(link: Favorite) = viewModelScope.launch {
        repository.insert(link)
    }

    fun getOneFav(link: String) = repository.getOneFav(link)

}

class FavViewModelFactory(private val repository: FavRepo) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(FavViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return FavViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

我面临哪些问题?

我收到一个错误说

java.lang.runtimeException:无法启动活动componentInfo {[删除的软件包名称] .mainactivity}:java.lang.illang.illegalstateexception:无法在主线程上访问数据库,因为它可能会长时间锁定UI, 。

到目前为止,我尝试过什么?

我已经尝试过 -

  • 在DAO的功能GetOneFav的前面添加悬挂,并且存储库
  • 使该函数在ViewModelScope中运行。它给出了与上述相同的错误。另外,通过这种方式,该函数返回了作业,而不是“喜欢的”数据类对象。
    fun getOneFav(link: String) = viewModelScope.launch {
        repository.getOneFav(link)
    }
  • 在此处遵循此方法 - 如何实现房间livedata filter 尽管有效,这似乎是如此简单的事情。同样,尽管该代码正在使用mutableLivedata,但插入发生时我无法看到任何触发器。

What am I trying to achieve ?

Get a single row of data which has the id I need. The SQL equivalent of SELECT * FROM favs WHERE link='link'. I have written a fun named getOneFav() which for this. I am following the tutorial https://developer.android.com/codelabs/android-room-with-a-view-kotlin#0 and code from https://github.com/android/sunflower

What have I setup so far ?

Entity

@Entity(tableName = "favs")
data class Favorite(
    @PrimaryKey @ColumnInfo(name = "link") val link : String,
    @ColumnInfo(name = "keywords") val keywords : String
)

DAO

@Dao
interface FavDAO {
    @Query("SELECT * FROM favs")
    fun getAllFavsLive(): Flow<List<Favorite>>

    @Query("SELECT * FROM favs WHERE link = :link")
    fun getOneFav(link: String): Favorite

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(link: Favorite)
}

Repository

class FavRepo (private val favDao: FavDAO) {

    val allFavs: Flow<List<Favorite>> = favDao.getAllFavsLive()

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun insert(link: Favorite) {
        favDao.insert(link)
    }

    fun getOneFav(link: String) = favDao.getOneFav(link)

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun delete(link: String) {
        favDao.delete(link)
    }
}

ViewModel

class FavViewModel (private val repository: FavRepo) : ViewModel() {

    val allFavs: LiveData<List<Favorite>> = repository.allFavs.asLiveData()

    fun insert(link: Favorite) = viewModelScope.launch {
        repository.insert(link)
    }

    fun getOneFav(link: String) = repository.getOneFav(link)

}

class FavViewModelFactory(private val repository: FavRepo) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(FavViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return FavViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

What problems am I facing ?

I am receiving an error saying

java.lang.RuntimeException: Unable to start activity ComponentInfo{[package name removed].MainActivity}: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

What have I tried so far ?

I have tried -

  • Adding suspend in front of the function getOneFav in DAO and Repository
  • Made the function run inside viewModelScope. It gave the same error as above. Also, this way the function returned a Job instead of the 'Favorite' data class object.
    fun getOneFav(link: String) = viewModelScope.launch {
        repository.getOneFav(link)
    }
  • Followed this method here - How to implement a Room LiveData filter which even though worked, which seemed like an overkill for something so simple. Also despite the fact that the code is using MutableLiveData, I wasn't able to see any triggers when the insert happened.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我最亲爱的 2025-02-13 12:29:42

您应该在不同的情况下运行查询:

class FavRepo (private val favDao: FavDAO) {

    val allFavs: Flow<List<Favorite>> = withContext(Dispatchers.IO) { 
        favDao.getAllFavsLive()
    }

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun insert(link: Favorite) = withContext(Dispatchers.IO) {
        favDao.insert(link)
    }

    fun getOneFav(link: String) = withContext(Dispatchers.IO) { 
        favDao.getOneFav(link)
    }

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun delete(link: String) = withContext(Dispatchers.IO) {
        favDao.delete(link)
    }
}

You should run your queries in a different context:

class FavRepo (private val favDao: FavDAO) {

    val allFavs: Flow<List<Favorite>> = withContext(Dispatchers.IO) { 
        favDao.getAllFavsLive()
    }

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun insert(link: Favorite) = withContext(Dispatchers.IO) {
        favDao.insert(link)
    }

    fun getOneFav(link: String) = withContext(Dispatchers.IO) { 
        favDao.getOneFav(link)
    }

    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun delete(link: String) = withContext(Dispatchers.IO) {
        favDao.delete(link)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文