簡體   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