目标是使用户从菜单中选择一个选项,并使会议室数据库中排序列中的顶部项显示为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并手动对卡片进行排序。
提前谢谢!