Home » Android » android – What is the difference between emit and emitSource with LiveData ? ( as in REAL time USE-CASE )

android – What is the difference between emit and emitSource with LiveData ? ( as in REAL time USE-CASE )

Posted by: admin June 15, 2020 Leave a comment

Questions:

emit accepts the data class whereas emitSource accepts LiveData<T> ( T -> data ). Considering the following example :- I have two type of calls :-

suspend fun getData(): Data // returns directly data

and the other one ;

suspend fun getData(): LiveData<Data> // returns live data instead

For the first case i can use:-

liveData {
   emit(LOADING)
   emit(getData())
}

My question : Using the above method would solve my problem , WHY do we need emitSource(liveData) anyway ?

Any good use-case for using the emitSource method would make it clear !

How to&Answers:

As you mentioned, I don’t think it solves anything in your stated problem, but I usually use it like this:

If I want to show cached data to the user from the db while I get fresh data from remote, with only emit it would look something like this:

liveData{
    emit(db.getData())
    val latest = webService.getLatestData()
    db.insert(latest)
    emit(db.getData())
}

But with emitSource it looks like this:

liveData{
    emitSource(db.getData())
    val latest = webService.getLatestData()
    db.insert(latest)
}

Don’t need to call emit again since the liveData already have a source.

Answer:

From what I understand emit(someValue) is similar to myData.value = someValue whereas emitSource(someLiveValue) is similar to myData = someLiveValue. This means that you can use emit whenever you want to set a value once, but if you want to connect your live data to another live data value you use emit source. An example would be emitting live data from a call to room (using emitSource(someLiveData)) then performing a network query and emitting an error (using emit(someError)).

Answer:

I found a real use-case which depicts the use of emitSource over emit which I have used many times in production now. 😀 The use-case:

Suppose u have some user data (User which has some fields like userId, userName ) returned by some ApiService.

The User Model:

data class User(var userId: String, var userName: String)

The userName is required by the view/activity to paint the UI. And the userId is used to make another API call which returns the UserData like profileImage , emailId.

The UserData Model:

data class UserData(var profileImage: String, var emailId: String)

This can be achieved internally using emitSource by wiring the two liveData in the ViewModel like:

User liveData –

val userLiveData: LiveData<User> = liveData {
   emit(service.getUser())
}

UserData liveData –

val userDataLiveData: LiveData<UserData> = liveData {
   emitSource(userLiveData.switchMap {
       liveData {
           emit(service.getUserData(it.userId))
       }
   })
}

So, in the activity / view one can ONLY call getUser() and the getUserData(userId) will be automatically triggered internally via switchMap.

You need not manually call the getUserData(id) by passing the id.

This is a simple example, imagine there is a chain of dependent-tasks which needs to be executed one after the other, each of which is observed in the activity. emitSource comes in handy

Answer:

With emitSource() you can not only emit a single value, but attach your LiveData to another LiveData and start emitting from it. Anyway, each emit() or emitSource() call will remove the previously added source.

var someData = liveData {
    val cachedData = dataRepository.getCachedData()
    emit(cachedData)

    val actualData = dataRepository.getData()
    emitSource(actualData)
}

The activity that’s observing the someData object, will quickly receive the cached data on the device and update the UI. Then, the LiveData itself will take care of making the network request and replace the cached data with a new live stream of data, that will eventually trigger the Activity observer and update the UI with the updated info.

Source: Exploring new Coroutines and Lifecycle Architectural Components integration on Android