观察到的LiveData在onMenuItemClick中没有更改

时间:2020-06-12 01:02:06

标签: android kotlin android-room android-livedata kotlin-coroutines

目标是使用户从菜单中选择一个选项,并使会议室数据库中排序列中的顶部项显示为TextView。单击菜单项时,我将其作为过滤器放置在DAO中,以便知道对值进行排序的列。问题在于,当我选择一个新值时该列不会更改,或者列表中的第一项返回null。使用我拥有的测试数据,我知道一个事实,那就是这些值没有求助。

CardDao

package com.example.android.pointmax.database

import androidx.lifecycle.LiveData
import androidx.room.*


@Dao
interface CardDao {

    @Query("SELECT * from Card")
    fun getCards(): LiveData<List<Card>>

    @Query("SELECT * FROM Card ORDER BY :categoryChosen DESC")
    fun getAllBestCards(categoryChosen: String?): LiveData<List<Card>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(card: Card)

    @Query("DELETE FROM Card")
    suspend fun deleteAll()

    @Query("DELETE FROM Card WHERE cardName = :name")
    suspend fun deleteByName(name: String)
}

CardRepository

package com.example.android.pointmax.database

import androidx.lifecycle.LiveData

// Declares the DAO as a private property in the constructor. Pass in the DAO
// instead of the whole database, because you only need access to the DAO
class CardRepository(private val cardDao: CardDao) {

    // Room executes all queries on a separate thread.
    // Observed LiveData will notify the observer when the data has changed.
    val allCards: LiveData<List<Card>> = cardDao.getCards()


    suspend fun insert(card: Card) {
        cardDao.insert(card)
    }

    suspend fun deleteByName(name: String){
        cardDao.deleteByName(name)
    }

    fun getAllBestCards(categoryChosen: String): LiveData<List<Card>> {
        return cardDao.getAllBestCards(categoryChosen)
    }

}

HomeFragment

package com.example.android.pointmax.ui.home

import android.os.Bundle
import android.view.*
import android.widget.EditText
import android.widget.PopupMenu
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.android.pointmax.R
import kotlinx.android.synthetic.main.fragment_home.*
import timber.log.Timber
import java.util.*
import kotlin.collections.ArrayDeque

class HomeFragment : Fragment(), PopupMenu.OnMenuItemClickListener  {

    private lateinit var viewModel: HomeViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        val application = requireNotNull(activity).application

        viewModel = ViewModelProvider(this).get(HomeViewModel::class.java)

        fun retrieveBestCard(categoryName: String) : String {
            val result = mutableListOf<String>()
            viewModel.getBestCardByCategory(categoryName).observe(viewLifecycleOwner, androidx.lifecycle.Observer {sortedCards->
                for(card in sortedCards) {
                    result += card.cardName
                }
            })
            return result[0]
        }

        category_button.setOnClickListener {
            val popupMenu = PopupMenu(context, category_button)
            val menuInflater: MenuInflater = popupMenu.menuInflater
            popupMenu.setOnMenuItemClickListener(this)
            menuInflater.inflate(R.menu.popup_menu, popupMenu.menu)
            popupMenu.show()

        }
    }

    override fun onMenuItemClick(item: MenuItem?): Boolean {
        var result = false

        if (item != null) {
            val category = item.title.toString().toLowerCase()
            Toast.makeText(context, "Selected Item: " + item.title, Toast.LENGTH_SHORT).show()
            viewModel.orderByCategory(category)
            viewModel.categoryObservable.observe(viewLifecycleOwner, androidx.lifecycle.Observer {bestCardList ->
                when (item.itemId) {
                    R.id.generalCategory -> {
                        Timber.i("$bestCardList")
                        result = true
                        return@Observer
                    }
                    R.id.groceriesCategory -> {
                        Timber.i("$bestCardList")
                        result = true
                        return@Observer
                    }
                    R.id.restaurantsCategory -> {
                        result = true
                    }
                    R.id.gasCategory -> {
                        result = true
                    }
                    R.id.airlinesCategory -> {
                        result = true
                    }
                    R.id.travelCategory -> {
                        result = true
                    }
                }
            })

        }
        return result
    }
}

HomeViewModel

package com.example.android.pointmax.ui.home

import android.app.Application
import androidx.lifecycle.*
import com.example.android.pointmax.database.Card
import com.example.android.pointmax.database.CardRepository
import com.example.android.pointmax.database.CardRoomDatabase

class HomeViewModel(application: Application) : AndroidViewModel(application) {

    private val repository: CardRepository
    // Using LiveData and caching what getAlphabetizedWords returns has several benefits:
    // - We can put an observer on the data (instead of polling for changes) and only update the
    //   the UI when the data actually changes.
    // - Repository is completely separated from the UI through the ViewModel.

    // Room executes all queries on a separate thread.
    // Observed LiveData will notify the observer when the data has changed.
    val allCards: LiveData<List<Card>>

    var mutableBestCard: MutableLiveData<String> = MutableLiveData()


    init {
        val cardsDao = CardRoomDatabase.getDatabase(application, viewModelScope).cardDao()
        repository = CardRepository(cardsDao)
        allCards = repository.allCards
    }

    fun getBestCardByCategory(category: String) : LiveData<List<Card>> {
        return repository.getAllBestCards(category)
    }


    val categoryObservable : LiveData<List<Card>> = Transformations.switchMap(mutableBestCard) { param ->
        repository.getAllBestCards(param)
    }


    fun orderByCategory(param: String){
        mutableBestCard.value = param
    }
}

对于观察LiveData和使用MenuItemClicked进行更改的任何建议,我将不胜感激。 如果无法按列对表进行排序并返回最高结果,那么我打算只使用allCard并手动对卡片进行排序。

提前谢谢!

0 个答案:

没有答案