带有房间数据库列表的 AlertDialog setItems:getValue() returns null

AlertDialog setItems with a list from room database: getValue() returns null

我只是想 select 从 AlertDialog 中我的房间数据库中的艺术家列表。从 viewModel 对 LiveData 对象调用 getValue() 始终给我 null。我真的需要为这么简单的东西制作一个 ListAdapter 吗?!为什么从数据库中获取一些字符串这么难?

ArtistDao

@Dao
interface ArtistDao {
    @Query("SELECT * FROM artist_table")
    fun getAllArtists(): Flow<List<Artist>>

    @Query("SELECT name FROM artist_table")
    fun getArtistList(): Flow<List<String>>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(artist: Artist)
}

Main 中的菜单选择选项 Activity

R.id.action_choose_artist -> {
            //create artist list
            val testList = songViewModel.artists.value
            val artistList = testList?.toTypedArray()

            // User chose choose artist action
            val alertDialog: AlertDialog? = this.let {
                val builder = AlertDialog.Builder(it)
                builder.apply {
                    setTitle(R.string.choose_artist)
                    setItems(artistList, DialogInterface.OnClickListener { dialog, which ->
                        // The 'which' argument contains the index position
                        // of the selected item
                        artistName = artistList!![which]
                    })
                }
                // Create the AlertDialog
                builder.create()
            }
            alertDialog?.show()
            true
        }

SongViewModel

val artists: LiveData<List<String>> = repository.artists.asLiveData()

歌曲库

val artists: Flow<List<String>> = artistDao.getArtistList()

你总是得到 null 因为没有人在观察你的 Flow->LiveData-chain。 LiveData 本身只会在有人观察它时触发并执行其工作。

在你的情况下,我认为你想要一个 one-time 请求来从你的数据库接收数据,并且应该使用挂起函数和协程来实现它。 Flow 在 Room DB 的上下文中仅当您对此查询的数据库更改感兴趣并想对此做出反应时才有用,例如通过在 RecyclerView.

中显示更新的数据

道:

@Dao
interface ArtistDao {
    @Query("SELECT name FROM artist_table")
    fun getArtistList(): List<String>
}

回购:

suspend fun getArtistList(): List<String> = artistDao.getArtistList()

视图模型:

fun getArtistList(onResult: (List<String>) -> Unit) {
  viewModelScope.launch{
      val artist = withContext(Dispatchers.IO){repository.getArtistList()}
      
      // maybe validate data, e.g. not empty

      onResult(artist)
    }
}

Activity:

R.id.action_choose_artist -> {
            //create artist list
            songViewModel.getArtistList { testList ->
                 val artistList = testList.toTypedArray()

                 // User chose choose artist action
                 ...
            }
        }