繁体   English   中英

ROOM/Android 使用 Repository 和 ViewModel 对列表进行排序 | 科特林

[英]ROOM/Android Sorting a List with Repository and ViewModel | Kotlin

当前问题:在第一次添加时,一个对象(Deck)被添加到无形中。 只有在从上下文菜单中选择了排序方法后,它才会出现。 但是,每次都必须重复此操作才能更新屏幕。

问题应该在存储库中作为 getAllDecks 引用 allDecks。 就好像 allDecks 没有更新数据或没有意识到它的 .value 正在改变。 因为 allDecks.postValue() 将从数据库中获取列表。 但这显然不是 LiveData<List>。 因此,它只做一次性的事情。 所以。 我将如何使存储库从数据库中读取不断的更新发生

我正在尝试对存储在存储库中的列表进行排序。 我的 ViewModel 有一个 List,它引用存储在存储库中的项目。 当用户按下上下文菜单项时会发生排序,这将更改存储库中的列表。 但是,此操作似乎不起作用。

我尝试使用调试工具,它显示正在调用 Repository 方法并且正在重新分配事物。 我相信这应该有效,因为我的 ViewModel 正在引用存储库,如果列表发生更改, MainActivity 会自动更新。

MainActivity 上下文菜单打开并响应 onClick 是根据所选项目对更改进行排序的文本。 因此,我知道它正在被调用。 我也知道自从我的更新、删除和插入查询工作以来,MainActivity 正在监听 ViewModel 的更改列表(Decks)。

出于某种原因,我一直在努力寻找与我的和 Kotlin 中类似的 StackOverflow 帖子。

最终,我想知道是否有人可以为我做错的事情指出正确的方向。 而且,您如何调试数据库查询的问题。 正如我发现当调试器转换为查看 SQLite 查询时,整个调试器进入循环。

亲切的问候,

PandaPlaysAll

主要活动(缩写)


         globalViewModel.sortBy(Sort.ALPHA_ASC) //Set default sorting

        //Listen for livedata changes in ViewModel. if there is, update recycler view
        globalViewModel.allDecks.observe(this, Observer { deck ->
            deck?.let { adapter.setDecks(deck) }
        })
 override fun onContextItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.sort_by_alpha_asc -> { globalViewModel.sortBy(Sort.ALPHA_ASC) ; currentSort = Sort.ALPHA_ASC ; contextMenuText.setText(R.string.sort_by_alpha_asc) ; return true; }
            R.id.sort_by_alpha_desc -> { globalViewModel.sortBy(Sort.ALPHA_DES) ; currentSort = Sort.ALPHA_DES ; contextMenuText.setText(R.string.sort_by_alpha_des) ; return true; }
            R.id.sort_by_completed_hidden -> { globalViewModel.sortBy(Sort.NON_COM) ; currentSort = Sort.NON_COM ; contextMenuText.setText(R.string.sort_by_non_complete) ; return true; }
            R.id.sort_by_due_date -> { globalViewModel.sortBy(Sort.DUE_DATE) ; currentSort = Sort.DUE_DATE ; contextMenuText.setText(R.string.sort_by_due_date) ; return true; }
            else -> return super.onContextItemSelected(item)
        }
    }


查看模型

  private val repository: DeckRepository
    val allDecks: LiveData<List<Deck>>

    init {
        val decksDao = FlashCardDB.getDatabase(application, viewModelScope).DeckDAO()
        repository = DeckRepository(deckDao = decksDao)
        allDecks = repository.getAllDecks()
    }

    fun sortBy(sortMethod: Sort) = viewModelScope.launch(Dispatchers.IO) {
        when (sortMethod) {
            Sort.ALPHA_ASC -> repository.sortBy(Sort.ALPHA_ASC)
            Sort.ALPHA_DES -> repository.sortBy(Sort.ALPHA_DES)
            Sort.NON_COM -> repository.sortBy(Sort.NON_COM)
            Sort.DUE_DATE -> repository.sortBy(Sort.DUE_DATE)
        }
    }

甲板存储库

private var allDecks = MutableLiveData<List<Deck>>() //instantiate object

    fun getAllDecks(): LiveData<List<Deck>> = allDecks //Repository handles livedata transmission. ViewModel references the actual Data.

    suspend fun sortBy(sortingMethod: Sort) {
        when (sortingMethod) {
            Sort.ALPHA_ASC -> allDecks.postValue(deckDao.getDecksSortedByAlphaAsc())
            Sort.ALPHA_DES -> allDecks.postValue(deckDao.getDecksSortedByAlphaDesc())
            Sort.NON_COM -> allDecks.postValue(deckDao.getDecksSortedByNonCompleted())
            Sort.DUE_DATE -> allDecks.postValue(deckDao.getDecksSortedByDueDate())
        }
    }

    suspend fun insert(deck: Deck) {
        deckDao.insert(deck)
    }

数据库

  //Sorting
    @Query("SELECT * from deck_table ORDER BY title ASC")
    fun getDecksSortedByAlphaAsc(): List<Deck>


    @Query("SELECT * from deck_table ORDER BY title DESC")
    fun getDecksSortedByAlphaDesc(): List<Deck>

    @Query("SELECT * from deck_table WHERE completed=1 ORDER BY title ASC")
    fun getDecksSortedByNonCompleted(): List<Deck>

    @Query("SELECT * from deck_table ORDER BY date ASC")
    fun getDecksSortedByDueDate(): List<Deck>


    //Modifying
    @Insert(onConflict = OnConflictStrategy.ABORT)
    suspend fun insert(deck: Deck)

您的活动未实时显示更改,因为您的存储库重新分配了其 LiveData。 虽然您让活动观察到单个 LiveData 的方法是正确的,但您实际上应该只更改它的值,而不是在有意义的情况下更改引用。

下面是一个例子:

存储库

private val allDecks = MutableLiveData<List<Deck>>()

fun getAllDecks(): LiveData<List<Deck>> = allDecks

fun sortBy(sortingMethod: Sort) {
    when (sortingMethod) {
        /* If you're handling your DB operations with coroutines, this function
         * should be suspendable and you should set the value to allDecks
         * with postValue
         */
        Sort.ALPHA_ASC -> allDecks.value = deckDao.getDecksSortedByAlphaAsc()
        Sort.ALPHA_DES -> allDecks.value = deckDao.getDecksSortedByAlphaDesc()
        Sort.NON_COM -> allDecks.value = deckDao.getDecksSortedByNonCompleted()
        Sort.DUE_DATE -> allDecks.value = deckDao.getDecksSortedByDueDate()
    }
}

因此,您的 DAO 查询将不再返回 LiveData,而是列表本身:

@Query("SELECT * from deck_table ORDER BY title ASC")
fun getDecksSortedByAlphaAsc(): List<Deck>


@Query("SELECT * from deck_table ORDER BY title DESC")
fun getDecksSortedByAlphaDesc(): List<Deck>

@Query("SELECT * from deck_table WHERE completed=1 ORDER BY title ASC")
fun getDecksSortedByNonCompleted(): List<Deck>

@Query("SELECT * from deck_table ORDER BY date ASC")
fun getDecksSortedByDueDate(): List<Deck>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM