I have the following in my viewmodel
val currentStockPriceAsLiveData: LiveData<UiState> = stockPriceDataSource.latestStockList
.map { listOfStock ->
UiState.Success(listOfStock)
}.asLiveData()
I observe this in my Activity in the onCreate method
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.currentStockPriceAsLiveData.observe(this@FlowUseCase1Activity) { uiState ->
if (uiState != null) {
if(uiState is UiState.Success) {
Timber.d("Received ${uiState.stockList.first()}")
}
render(uiState)
}
}
}
}
}
I am using repeatOnLifeCycle to only observe when the lifecycle is at least STARTED state. This works as if I put the app in the background it will stop observing.
However, the problem is when I bring the app back to the foreground it will trigger duplicated emissions. And when I put the app to the background a second time it will trigger triple emissions.
From my log:
00:00:05.274 23476-23476 D Received Stock(rank=1, name=Apple, symbol=AAPL, marketCap=2.37819317E12, country=United States, currentPrice=142.95015, currency=DOLLAR, priceTrend=UNKNOWN)
00:00:05.275 23476-23476 D Received Stock(rank=1, name=Apple, symbol=AAPL, marketCap=2.37819317E12, country=United States, currentPrice=142.95015, currency=DOLLAR, priceTrend=UNKNOWN)
00:00:05.276 23476-23476 D Received Stock(rank=1, name=Apple, symbol=AAPL, marketCap=2.37819317E12, country=United States, currentPrice=142.95015, currency=DOLLAR, priceTrend=UNKNOWN)
As you can see its like its triggering 3 times at the same time.
I think it is because when I put the app to the background the viewmodel has not been destroyed, so when I put the app back in the foreground it creates subsequent observers.
Is there a way to prevent this?
You don't have to manage the lifecycle of LiveData
. LiveData
manages its own lifecycle. It will pause or resume based on lifecycle of containing Activity
and Fragment
.
Use LiveData
like this in onCreate()
viewModel.currentStockPriceAsLiveData.observe(this@FlowUseCase1Activity) { uiState ->
if (uiState != null) {
if(uiState is UiState.Success) {
Timber.d("Received ${uiState.stockList.first()}")
}
render(uiState)
}
}
I don't know exactly why it's duplicating. It may be because you attach a new observer each time the lifecycle reach STARTED STATE
. LiveData
does not need to be attached each time the lifecycle changes. It manages its own lifecycle. Call live data as shown above in onCreate()
just once.