tring yuo
tring yuo

Reputation: 67

Android Kotlin SingleLiveEvent With Flow

I am using a livedata on viewmodel and flow on repository and data source. when I tried to connect them to each other and get a data stream as below that error occurred

Error

java.lang.ClassCastException: androidx.lifecycle.CoroutineLiveData cannot be cast to com.versec.versecko.util.SingleLiveEvent

ViewModel

val singleChat : SingleLiveEvent<ChatRoomEntity> = repository.getChatRooms().asLiveData() as SingleLiveEvent<ChatRoomEntity>

Fragment

viewModel.singleChat.observe(viewLifecycleOwner, Observer {

        roomList.add(it)
        chatRoomAdapter.changeRooms(roomList)
        chatRoomAdapter.notifyDataSetChanged()
    })

SingleLiveEvent

class SingleLiveEvent<T> : MutableLiveData<T>() {

companion object {

    private val TAG = "SingleLiveEvent"
}

private val pending : AtomicBoolean = AtomicBoolean(false)


@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {


    if (hasActiveObservers()) { Log.w(TAG, "Multiple Observers ,,,")}

    super.observe(owner, Observer { t ->
        if (pending.compareAndSet(true, false)) {
            observer.onChanged(t)
        }
    })

}

@MainThread
override fun setValue(value: T?) {
    pending.set(true)
    super.setValue(value)
}

@MainThread
fun call() {value = null }       }

what is the proper way to use both??

Upvotes: -1

Views: 1646

Answers (1)

Arpit Shukla
Arpit Shukla

Reputation: 10493

From what I understood, the reason you are using SingleLiveData is because you don't want the observer to receive same ChatRoomEntity twice in which case it will be duplicated in the list. A simple solution to this is to maintain the list inside the ViewModel and expose this list to the UI, then you won't have to use workarounds like SingleLiveData.

// ViewModel
private val _chatRoomsLiveData = MutableLiveData(emptyList<ChatRoomEntity>())
val chatRoomsLiveData: LiveData<List<ChatRoomEntity>> = _chatRoomsLiveData

init {
    viewModelScope.launch {
        repository.getChatRooms().collect {
            _chatRoomsLiveData.value = _chatRoomsLiveData.value!! + it
        }
    }
}

// Fragment
viewModel.chatRoomsLiveData.observe(viewLifecycleOwner, Observer {
    chatRoomAdapter.changeRooms(it)
    chatRoomAdapter.notifyDataSetChanged()
})

Upvotes: 1

Related Questions