This is a chatting app and I am using LiveData to observe new updated messages on Firebase Realtime Database. but when I open its activity, LiveData was called and the last message in Firebase Realtime Databaseadded to the message list in the activity even though any message in Firebase Realtime Database was not added.
My logic is to first get all messages from Realtime Database with getAllMessages function and then get newly updated messages also from Realtime Database with getUpdatedMessage function when others send messages to me but the problem above happened.
I do not know where problem is from livedata itself or addChildEventListener ,,,
How can I avoid the first callback of LiveData after its registration in onCreate?
Activity
class RoomActivity : AppCompatActivity() {
private lateinit var binding : ActivityRoomBinding
private val viewModel : RoomViewModel by viewModel<RoomViewModel>()
private var room : ChatRoomEntity? = ChatRoomEntity()
private val messageList = mutableListOf<MessageEntity>()
private lateinit var adapter: MessageAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_room)
binding.lifecycleOwner = this
val intent = getIntent()
room = intent.getSerializableExtra("room") as? ChatRoomEntity
binding.recyclerMessages.layoutManager = LinearLayoutManager(this)
adapter = MessageAdapter(messageList)
binding.recyclerMessages.adapter = adapter
viewModel.getAllMessage(room!!.chatRoomUid).observe(this, Observer {
adapter.changeMessages(it)
adapter.notifyDataSetChanged()
})
viewModel.getUpdatedMessage(room!!.chatRoomUid).observe(this, Observer {
adapter.updateMessage(it)
adapter.notifyDataSetChanged()
})
binding.buttonSend.setOnClickListener {
if (binding.editMessage.text!!.length>0) {
viewModel.sendMessage(binding.editMessage.text!!.toString(), room!!)
}
}
} }
ViewModel
class RoomViewModel (
private val repository: ChatRepository
) : ViewModel() {
fun getAllMessage (roomUid : String) : LiveData<MutableList<MessageEntity>> {
val _messageList = MutableLiveData<MutableList<MessageEntity>>()
viewModelScope.launch {
_messageList.postValue(repository.getAllMessages(roomUid))
}
return _messageList
}
fun sendMessage(contents : String, room : ChatRoomEntity ) {
repository.sendMessage(contents, room)
}
fun getUpdatedMessage(roomUid: String) = repository.getUpdatedMessage(roomUid).asLiveData() }
DataSourceImpl
override fun getUpdatedMessage(chatRoomUid: String): Flow<MessageEntity> = callbackFlow {
val reference = databaseReference.child("chat").child("messageList").child(chatRoomUid)
val subscription = reference.addChildEventListener(object : ChildEventListener{
override fun onChildAdded(
snapshot: DataSnapshot,
previousChildName: String?
) {
Log.d("message-get", "getUpdatedMessage-added")
trySend(snapshot.getValue(MessageEntity::class.java)!!)
}
override fun onChildChanged(
snapshot: DataSnapshot,
previousChildName: String?
) {
}
override fun onChildRemoved(snapshot: DataSnapshot) {
}
override fun onChildMoved(
snapshot: DataSnapshot,
previousChildName: String?
) {
}
override fun onCancelled(error: DatabaseError) {
}
})
awaitClose { reference.removeEventListener(subscription) }
}