Smaily Carrilho
Smaily Carrilho

Reputation: 131

Kotlin & Room: return id from inserted not working

I want to get the id from de newly inserted data on database. I'm using Room and Kotlin. I've already tried a lot of solutions that I found here on StackOverFlow, but I couldn't achieve this.

Here's my code:

Dao (AvaliacaoDao.kt)

interface AvaliacaoDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun addAvaliacao(avaliacao: Avaliacao) : Long
... 
}

Repository (AvaliacaoRepository.kt)

class AvaliacaoRepository(private val avaliacaoDao: AvaliacaoDao) {

    suspend fun addAvaliacao(avaliacao: Avaliacao) : Long {
        val longId = avaliacaoDao.addAvaliacao(avaliacao)
        Log.d("AvaliacaoRepository", longId.toString())
        return longId
    }
... 
}

ViewModel (AvaliacaoViewModel.kt)

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

    var returnedVal: MutableLiveData<Long> = MutableLiveData()

    fun addAvaliacao(avaliacao: Avaliacao) {
        viewModelScope.launch(Dispatchers.IO) {
            val resultRepo = repository.addAvaliacao(avaliacao)
            returnedVal.postValue(resultRepo)
            Log.d("AvaliacaoViewModel", "Avaliação id: $resultRepo")
        }
    }
... 
}

Fragment (AddAvaliacaoFragment.kt)

class AddAvaliacaoFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        insertDataToDatabase()
    }

    private fun insertDataToDatabase(){
        val dataCriacao = binding.dataCriacaoAvaliacaoEditText.text.toString()
        val nomeAvaliacao = binding.nomeAvaliacaoEditText.text.toString()
        Log.d(TAG, "dataCriacao: $dataCriacao, nome avaliação: $nomeAvaliacao")

        if(inputCheck(dataCriacao, nomeAvaliacao)){
            // Criar objeto Avaliação
            val avaliacao: Avaliacao = Avaliacao(
                0,
                nomeAvaliacao,
                dataCriacao,
                0f,
                0f,
                0,
                0,
                0
            )

            // Adicionar dados ao Banco de Dados
            mAvaliacaoViewModel.addAvaliacao(avaliacao)

            mAvaliacaoViewModel.returnedVal.observe(viewLifecycleOwner, Observer {
                Log.d(TAG, "Observer Avaliação ID: $it")
            })

            Toast.makeText(requireContext(), getString(R.string.avaliacao_add_sucesso), Toast.LENGTH_SHORT).show()

            // Navegar de volta pra lista de Avaliações
            findNavController().navigate(R.id.action_addAvaliacaoFragment_to_navigation_avaliacoes)

        } else {

            Toast.makeText(requireContext(), getString(R.string.avaliacao_add_erro), Toast.LENGTH_SHORT).show()
        }
    }

    private fun inputCheck(dataCriacao: String, nomeAvaliacao: String): Boolean{
        return !(TextUtils.isEmpty(dataCriacao) && TextUtils.isEmpty(nomeAvaliacao)
                && TextUtils.equals(dataCriacao, "") && TextUtils.equals(nomeAvaliacao, ""))
    }

}

Gradle

implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-process:2.2.0'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.0-rc03"

def room_version = "2.2.6"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"

At console, I get the log from repository and viewModel, but the returnedVal observer at fragment don't work and I can't get the returned id from inserted data.

Can anyone help me, please?

Upvotes: 0

Views: 289

Answers (1)

Muhammad Ahmed
Muhammad Ahmed

Reputation: 1048

Bind your view model after onViewCreated

class AddAvaliacaoFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        bindViewModel()
        insertDataToDatabase()
    }

    private fun bindViewModel() {
       mAvaliacaoViewModel.returnedVal.observe(viewLifecycleOwner, Observer {
           // Navegar de volta pra lista de Avaliações
            findNavController().navigate(R.id.action_addAvaliacaoFragment_to_navigation_avaliacoes)     
       })
    }

    private fun insertDataToDatabase(){
        val dataCriacao = binding.dataCriacaoAvaliacaoEditText.text.toString()
        val nomeAvaliacao = binding.nomeAvaliacaoEditText.text.toString()
        Log.d(TAG, "dataCriacao: $dataCriacao, nome avaliação: $nomeAvaliacao")

        if(inputCheck(dataCriacao, nomeAvaliacao)){
            // Criar objeto Avaliação
            val avaliacao: Avaliacao = Avaliacao(
                0,
                nomeAvaliacao,
                dataCriacao,
                0f,
                0f,
                0,
                0,
                0
            )

            // Adicionar dados ao Banco de Dados
            mAvaliacaoViewModel.addAvaliacao(avaliacao)

            

            Toast.makeText(requireContext(), getString(R.string.avaliacao_add_sucesso), Toast.LENGTH_SHORT).show()

            

        } else {

            Toast.makeText(requireContext(), getString(R.string.avaliacao_add_erro), Toast.LENGTH_SHORT).show()
        }
    }

    private fun inputCheck(dataCriacao: String, nomeAvaliacao: String): Boolean{
        return !(TextUtils.isEmpty(dataCriacao) && TextUtils.isEmpty(nomeAvaliacao)
                && TextUtils.equals(dataCriacao, "") && TextUtils.equals(nomeAvaliacao, ""))
    }

}

For Handling Event only once you can use SingleLiveEvent or you can check this article

https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

Upvotes: 1

Related Questions