Обработка LiveData из базы данных Room в ViewModel с помощью Transformations.map - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть следующая простая база данных:

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
    ...
}

В настоящее время я хочу получить и обработать только последнюю запись в этой непустой базе данных (без изменения / добавления методов в NameListDao).

Внутри фрагмента легко получить и, например, отобразить (в TextView через привязку данных) последнюю запись в базе данных, используя метод observe:

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

Насколько я узнал в ViewModel необходимо использовать Transformations.map или Transformations.switchMap для обработки LiveData. Я попробовал следующие два (четыре) подхода с преобразованиями (ни один из которых не работал), чтобы получить последнюю запись в базе данных и передать ее методу doSomethingWithName(). Однако во всех случаях передаваемый параметр был, по-видимому, пустым. (Я также попробовал первую запись через [0], но я получил те же результаты)

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
    }
}

Что мне здесь не хватает?

1 Ответ

1 голос
/ 06 февраля 2020

Если вы хотите получить последнее значение в списке, учитывая, что список также может быть пустым ...

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
    }

}

...