简体   繁体   中英

Processing LiveData from Room database in ViewModel with Transformations.map

I have the following simple database:

NameList.kt

@Entity(tableName = "name_list")
data class NameList(
        @PrimaryKey(autoGenerate = true)
        var id: Long = 0L,

        @ColumnInfo(name = "name")
        var name: String = "")

NameListDao.kt

@Dao
interface NameListDao{    
    @Insert
    fun insert(nameList: NameList)

    @Update
    fun update(nameList: NameList)

    @Query("SELECT * FROM name_list ORDER BY id DESC")
    fun getAll(): LiveData<List<NameList>>
}

NameListRepository.kt

class NameListRepository(private val nameListDao: NameListDao){
    val allNames: LiveData<List<NameList>> = nameListDao.getAll()
}

MyViewModel.kt

class MyViewModel(app: Application): AndroidViewModel(app){
    private val nameListDao = NameListDatabase.getInstance(app).nameListDao
    private val repository: nameListRepository = nameListRepository(nameListDao)
    private val allNames: LiveData <List<NameList>> = repository.allNames
    ...
}

For the time being I want to get and process only the last entry of this non-empty database (without changing/adding methods in NameListDao ).

Within a fragment, it is easy to get and eg display (in a TextView via data binding) the last database entry using the observe method:

viewModel.allNames.observe(this, Observer<List<NameList?>> { 
    nameList ->  binding.textView.text = nameList[nameList.lastIndex]!!.name 
}) 

As far as I found out, in ViewModel one needs to use Transformations.map or Transformations.switchMap to process LiveData . I tried the following two (four) approaches with Transformations (none of which worked) in order to get the last entry of the database and pass it on to the method doSomethingWithName() . However, in all cases the passed parameter was apparently empty. (I also tried the first entry via [0] , but I got the same results though)

class MyViewModel(app: Application): AndroidViewModel(app){
    private val nameListDao = NameListDatabase.getInstance(app).nameListDao
    private val repository: nameListRepository = nameListRepository(nameListDao)
    private val allNames: LiveData <List<NameList>> = repository.allNames

    private var _lastName = ""

    init{
        Transformations.map(allNames, ::getLastName1)          //first try
        //Transformations.switchMap(allNames, ::getLastName2)  //second try    

        doSomethingWithName(_lastName) //commented when executed in getLastName()
    }

    private fun doSomethingWithName(name: String){ ... }

    private fun getLastName1(nameList: List<NameList>){
        val names: MutableList<String> = ArrayList()
        nameList.forEach { names.add(it.name) } 
        val lastName = names[names.lastIndex]
        //doSomethingWithName(lastName) //third try
        _lastName = lastName
    }

    private fun getLastName2(nameList: List<NameList>): LiveData<NameList>{
        val liveData: MutableLiveData<NameList> = MutableLiveData(nameList[nameList.lastIndex])
        val lastName = liveData.value!!.name
        //doSomethingWithName(lastName) //fourth try
        _lastName = lastName
        return liveData
    }
}

What am I missing here?

If you want to get the last value in the list, considering the list might also be empty...

class MyViewModel(app: Application): AndroidViewModel(app){
    private val nameListDao = NameListDatabase.getInstance(app).nameListDao
    private val repository: nameListRepository = nameListRepository(nameListDao)
    private val allNames: LiveData <List<NameList>> = repository.allNames
    private var _lastName = ""

    private val theLatestName =  MutableLiveData<NameList?>()
    init {
       allNames.observe(getAReferenceToaLifeCycleOwner, Observer{
         theLastestName.postValue(it.lastOrNull())
       })
       //make sure to get rid of the observer once this instance
       //of the viewmodel is destroyed
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM