简体   繁体   English

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

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

current issue: During the first time adding, an object (Deck) is added invisibly.当前问题:在第一次添加时,一个对象(Deck)被添加到无形中。 It will only appear once the sorting method has been chosen from the context menu.只有在从上下文菜单中选择了排序方法后,它才会出现。 However, this has to be repeated each time for the screen to be updated.但是,每次都必须重复此操作才能更新屏幕。

The issue should lie within the Repository as getAllDecks in referencing allDecks.问题应该在存储库中作为 getAllDecks 引用 allDecks。 It is as if the allDecks is not updating the data or not realising its .value is changing.就好像 allDecks 没有更新数据或没有意识到它的 .value 正在改变。 As allDecks.postValue() will in take the List from the database.因为 allDecks.postValue() 将从数据库中获取列表。 But this obviously isn't a LiveData<List>.但这显然不是 LiveData<List>。 Thus, it only does a one time thing.因此,它只做一次性的事情。 So.所以。 How would I make the occur with the repository reading the constant updates from the database我将如何使存储库从数据库中读取不断的更新发生

I am trying to sort through a list stored in the Repository.我正在尝试对存储在存储库中的列表进行排序。 My ViewModel has a List that is referencing the items stored in the repository.我的 ViewModel 有一个 List,它引用存储在存储库中的项目。 Sorting occurs when a user presses a context menu item and that will change the list in the Repository.当用户按下上下文菜单项时会发生排序,这将更改存储库中的列表。 However, this action doesn't seem to be working.但是,此操作似乎不起作用。

I tried using the debugging tool and it showed me that the Repository method was being called and things were being reassigned.我尝试使用调试工具,它显示正在调用 Repository 方法并且正在重新分配事物。 I believed this should have worked as my ViewModel was referencing the repository and MainActivity would automatically update if the list had changed.我相信这应该有效,因为我的 ViewModel 正在引用存储库,如果列表发生更改, MainActivity 会自动更新。

The MainActivity context menu opens and reacts to the onClick is the text for sorting changes depending on the chosen item. MainActivity 上下文菜单打开并响应 onClick 是根据所选项目对更改进行排序的文本。 Thus, I know it is being called.因此,我知道它正在被调用。 I also know since my update, delete and insert queries are working that MainActivity is listening to the ViewModel's changing list (of Decks).我也知道自从我的更新、删除和插入查询工作以来,MainActivity 正在监听 ViewModel 的更改列表(Decks)。

For some reason, I have struggled finding any StackOverflow posts similar to mine and in Kotlin.出于某种原因,我一直在努力寻找与我的和 Kotlin 中类似的 StackOverflow 帖子。

Ultimately, I was wondering if someone could point in the right direction for what I am doing wrong.最终,我想知道是否有人可以为我做错的事情指出正确的方向。 AND also, how do you debug issues with the database queries.而且,您如何调试数据库查询的问题。 As I find when the debugger transitions to viewing the SQLite query, the whole debugger gets in a loop.正如我发现当调试器转换为查看 SQLite 查询时,整个调试器进入循环。

Kind regards,亲切的问候,

PandaPlaysAll PandaPlaysAll

Main Activity (abbreviated)主要活动(缩写)


         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)
        }
    }


View Model查看模型

  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)
        }
    }

DeckRepository甲板存储库

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)
    }

Database数据库

  //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)

Your activity isn't showing the changes in real time because your repository reassigns its LiveData.您的活动未实时显示更改,因为您的存储库重新分配了其 LiveData。 While your approach of having a single LiveData to be observed by the activity is correct, you should actually change only its value, not the reference if that makes sense.虽然您让活动观察到单个 LiveData 的方法是正确的,但您实际上应该只更改它的值,而不是在有意义的情况下更改引用。

Here's an example:下面是一个例子:

Repository存储库

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()
    }
}

Consequently, your DAO queries will no longer return LiveData, but the lists themselves:因此,您的 DAO 查询将不再返回 LiveData,而是列表本身:

DAO

@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