Challenge 1: viewModelScope Cleanup — Solution class PollingViewModel : ViewModel() { fun startPolling() { viewModelScope.launch { while (true) { delay(2000) Log.d("PollingViewModel", "Polling tick") } } } } // When does this loop stop, and why is no explicit cancel() needed? // // The loop stops the moment this ViewModel is cleared — which happens // when the screen that owns it is genuinely finished (the user navigates // away permanently, not just rotates the device, since Chapter 2 // established the ViewModel survives rotation). ViewModel's base class // calls viewModelScope.cancel() internally inside its own onCleared() // callback, which cancels every coroutine ever launched via // viewModelScope — including this while(true) loop, mid-delay() or // mid-iteration, wherever it happens to be. No cancel() call is ever // written inside PollingViewModel itself because viewModelScope's // cancellation is tied automatically to the ViewModel's own lifetime by // the framework, not something this class needs to manage manually. Notes: - while (true) with delay(2000) inside is a common polling pattern — it relies entirely on external cancellation (via viewModelScope) to ever stop, since there's no internal exit condition in the loop itself. - This is the same "structured concurrency" guarantee from Kotlin Intermediate Chapter 2 — a coroutine tied to a scope is automatically cancelled when that scope ends, with zero manual bookkeeping.