Reputation: 131
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
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
Upvotes: 1