1 /* <lambda>null2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package androidx.lifecycle 17 18 import androidx.annotation.MainThread 19 import androidx.annotation.RestrictTo 20 import kotlin.coroutines.CoroutineContext 21 import kotlin.jvm.JvmStatic 22 import kotlinx.coroutines.CoroutineScope 23 import kotlinx.coroutines.Dispatchers 24 import kotlinx.coroutines.SupervisorJob 25 import kotlinx.coroutines.cancel 26 import kotlinx.coroutines.channels.awaitClose 27 import kotlinx.coroutines.flow.Flow 28 import kotlinx.coroutines.flow.MutableStateFlow 29 import kotlinx.coroutines.flow.StateFlow 30 import kotlinx.coroutines.flow.asStateFlow 31 import kotlinx.coroutines.flow.callbackFlow 32 import kotlinx.coroutines.flow.flowOn 33 import kotlinx.coroutines.launch 34 35 /** 36 * Defines an object that has an Android Lifecycle. [Fragment][androidx.fragment.app.Fragment] and 37 * [FragmentActivity][androidx.fragment.app.FragmentActivity] classes implement [LifecycleOwner] 38 * interface which has the [ getLifecycle][LifecycleOwner.getLifecycle] method to access the 39 * Lifecycle. You can also implement [LifecycleOwner] in your own classes. 40 * 41 * [Event.ON_CREATE], [Event.ON_START], [Event.ON_RESUME] events in this class are dispatched 42 * **after** the [LifecycleOwner]'s related method returns. [Event.ON_PAUSE], [Event.ON_STOP], 43 * [Event.ON_DESTROY] events in this class are dispatched **before** the [LifecycleOwner]'s related 44 * method is called. For instance, [Event.ON_START] will be dispatched after 45 * [onStart][android.app.Activity.onStart] returns, [Event.ON_STOP] will be dispatched before 46 * [onStop][android.app.Activity.onStop] is called. This gives you certain guarantees on which state 47 * the owner is in. 48 * 49 * To observe lifecycle events call [.addObserver] passing an object that implements either 50 * [DefaultLifecycleObserver] or [LifecycleEventObserver]. 51 */ 52 public abstract class Lifecycle { 53 /** 54 * Lifecycle coroutines extensions stashes the CoroutineScope into this field. 55 * 56 * RestrictTo as it is used by lifecycle-common-ktx 57 */ 58 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 59 @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 60 @set:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 61 public var internalScopeRef: AtomicReference<Any?> = AtomicReference(null) 62 63 /** 64 * Adds a LifecycleObserver that will be notified when the LifecycleOwner changes state. 65 * 66 * The given observer will be brought to the current state of the LifecycleOwner. For example, 67 * if the LifecycleOwner is in [State.STARTED] state, the given observer will receive 68 * [Event.ON_CREATE], [Event.ON_START] events. 69 * 70 * @param observer The observer to notify. 71 */ 72 @MainThread public abstract fun addObserver(observer: LifecycleObserver) 73 74 /** 75 * Removes the given observer from the observers list. 76 * 77 * If this method is called while a state change is being dispatched, 78 * * If the given observer has not yet received that event, it will not receive it. 79 * * If the given observer has more than 1 method that observes the currently dispatched event 80 * and at least one of them received the event, all of them will receive the event and the 81 * removal will happen afterwards. 82 * 83 * @param observer The observer to be removed. 84 */ 85 @MainThread public abstract fun removeObserver(observer: LifecycleObserver) 86 87 /** 88 * Returns the current state of the Lifecycle. 89 * 90 * @return The current state of the Lifecycle. 91 */ 92 @get:MainThread public abstract val currentState: State 93 94 /** 95 * Returns a [StateFlow] where the [StateFlow.value] represents the current [State] of this 96 * Lifecycle. 97 * 98 * @return [StateFlow] where the [StateFlow.value] represents the current [State] of this 99 * Lifecycle. 100 */ 101 public open val currentStateFlow: StateFlow<Lifecycle.State> 102 get() { 103 val mutableStateFlow = MutableStateFlow(currentState) 104 LifecycleEventObserver { _, event -> mutableStateFlow.value = event.targetState } 105 .also { addObserver(it) } 106 return mutableStateFlow.asStateFlow() 107 } 108 109 public enum class Event { 110 /** Constant for onCreate event of the [LifecycleOwner]. */ 111 ON_CREATE, 112 113 /** Constant for onStart event of the [LifecycleOwner]. */ 114 ON_START, 115 116 /** Constant for onResume event of the [LifecycleOwner]. */ 117 ON_RESUME, 118 119 /** Constant for onPause event of the [LifecycleOwner]. */ 120 ON_PAUSE, 121 122 /** Constant for onStop event of the [LifecycleOwner]. */ 123 ON_STOP, 124 125 /** Constant for onDestroy event of the [LifecycleOwner]. */ 126 ON_DESTROY, 127 128 /** An [Event] constant that can be used to match all events. */ 129 ON_ANY; 130 131 /** 132 * Returns the new [Lifecycle.State] of a [Lifecycle] that just reported this 133 * [Lifecycle.Event]. 134 * 135 * Throws [IllegalArgumentException] if called on [.ON_ANY], as it is a special value used 136 * by [OnLifecycleEvent] and not a real lifecycle event. 137 * 138 * @return the state that will result from this event 139 */ 140 public val targetState: State 141 get() { 142 when (this) { 143 ON_CREATE, 144 ON_STOP -> return State.CREATED 145 ON_START, 146 ON_PAUSE -> return State.STARTED 147 ON_RESUME -> return State.RESUMED 148 ON_DESTROY -> return State.DESTROYED 149 ON_ANY -> {} 150 } 151 throw IllegalArgumentException("$this has no target state") 152 } 153 154 public companion object { 155 /** 156 * Returns the [Lifecycle.Event] that will be reported by a [Lifecycle] leaving the 157 * specified [Lifecycle.State] to a lower state, or `null` if there is no valid event 158 * that can move down from the given state. 159 * 160 * @param state the higher state that the returned event will transition down from 161 * @return the event moving down the lifecycle phases from state 162 */ 163 @JvmStatic 164 public fun downFrom(state: State): Event? { 165 return when (state) { 166 State.CREATED -> ON_DESTROY 167 State.STARTED -> ON_STOP 168 State.RESUMED -> ON_PAUSE 169 else -> null 170 } 171 } 172 173 /** 174 * Returns the [Lifecycle.Event] that will be reported by a [Lifecycle] entering the 175 * specified [Lifecycle.State] from a higher state, or `null` if there is no valid event 176 * that can move down to the given state. 177 * 178 * @param state the lower state that the returned event will transition down to 179 * @return the event moving down the lifecycle phases to state 180 */ 181 @JvmStatic 182 public fun downTo(state: State): Event? { 183 return when (state) { 184 State.DESTROYED -> ON_DESTROY 185 State.CREATED -> ON_STOP 186 State.STARTED -> ON_PAUSE 187 else -> null 188 } 189 } 190 191 /** 192 * Returns the [Lifecycle.Event] that will be reported by a [Lifecycle] leaving the 193 * specified [Lifecycle.State] to a higher state, or `null` if there is no valid event 194 * that can move up from the given state. 195 * 196 * @param state the lower state that the returned event will transition up from 197 * @return the event moving up the lifecycle phases from state 198 */ 199 @JvmStatic 200 public fun upFrom(state: State): Event? { 201 return when (state) { 202 State.INITIALIZED -> ON_CREATE 203 State.CREATED -> ON_START 204 State.STARTED -> ON_RESUME 205 else -> null 206 } 207 } 208 209 /** 210 * Returns the [Lifecycle.Event] that will be reported by a [Lifecycle] entering the 211 * specified [Lifecycle.State] from a lower state, or `null` if there is no valid event 212 * that can move up to the given state. 213 * 214 * @param state the higher state that the returned event will transition up to 215 * @return the event moving up the lifecycle phases to state 216 */ 217 @JvmStatic 218 public fun upTo(state: State): Event? { 219 return when (state) { 220 State.CREATED -> ON_CREATE 221 State.STARTED -> ON_START 222 State.RESUMED -> ON_RESUME 223 else -> null 224 } 225 } 226 } 227 } 228 229 /** 230 * Lifecycle states. You can consider the states as the nodes in a graph and [Event]s as the 231 * edges between these nodes. 232 */ 233 public enum class State { 234 /** 235 * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch 236 * any more events. For instance, for an [android.app.Activity], this state is reached 237 * **right before** Activity's [onDestroy][android.app.Activity.onDestroy] call. 238 */ 239 DESTROYED, 240 241 /** 242 * Initialized state for a LifecycleOwner. For an [android.app.Activity], this is the state 243 * when it is constructed but has not received [onCreate][android.app.Activity.onCreate] 244 * yet. 245 */ 246 INITIALIZED, 247 248 /** 249 * Created state for a LifecycleOwner. For an [android.app.Activity], this state is reached 250 * in two cases: 251 * * after [onCreate][android.app.Activity.onCreate] call; 252 * * **right before** [onStop][android.app.Activity.onStop] call. 253 */ 254 CREATED, 255 256 /** 257 * Started state for a LifecycleOwner. For an [android.app.Activity], this state is reached 258 * in two cases: 259 * * after [onStart][android.app.Activity.onStart] call; 260 * * **right before** [onPause][android.app.Activity.onPause] call. 261 */ 262 STARTED, 263 264 /** 265 * Resumed state for a LifecycleOwner. For an [android.app.Activity], this state is reached 266 * after [onResume][android.app.Activity.onResume] is called. 267 */ 268 RESUMED; 269 270 /** 271 * Compares if this State is greater or equal to the given `state`. 272 * 273 * @param state State to compare with 274 * @return true if this State is greater or equal to the given `state` 275 */ 276 public fun isAtLeast(state: State): Boolean { 277 return compareTo(state) >= 0 278 } 279 } 280 } 281 282 /** An object reference that may be updated atomically. */ 283 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 284 public expect class AtomicReference<V> 285 /** Creates a new [AtomicReference] with the given [initialValue]. */ 286 public constructor(initialValue: V) { 287 288 /** Returns the current value. */ getnull289 public fun get(): V 290 291 /** Atomically sets the value to [newValue] if the current value is equal to [expectedValue]. */ 292 public fun compareAndSet(expectedValue: V, newValue: V): Boolean 293 } 294 295 /** 296 * [CoroutineScope] tied to this [Lifecycle]. 297 * 298 * This scope will be cancelled when the [Lifecycle] is destroyed. 299 * 300 * This scope is bound to 301 * [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate] 302 */ 303 public val Lifecycle.coroutineScope: LifecycleCoroutineScope 304 get() { 305 while (true) { 306 val existing = internalScopeRef.get() as LifecycleCoroutineScopeImpl? 307 if (existing != null) { 308 return existing 309 } 310 val newScope = 311 LifecycleCoroutineScopeImpl(this, SupervisorJob() + Dispatchers.Main.immediate) 312 if (internalScopeRef.compareAndSet(null, newScope)) { 313 newScope.register() 314 return newScope 315 } 316 } 317 } 318 319 /** 320 * [CoroutineScope] tied to a [Lifecycle] and 321 * [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate] 322 * 323 * This scope will be cancelled when the [Lifecycle] is destroyed. 324 */ 325 public expect abstract class LifecycleCoroutineScope internal constructor() : CoroutineScope { 326 internal abstract val lifecycle: Lifecycle 327 } 328 329 internal class LifecycleCoroutineScopeImpl( 330 override val lifecycle: Lifecycle, 331 override val coroutineContext: CoroutineContext 332 ) : LifecycleCoroutineScope(), LifecycleEventObserver { 333 init { 334 // in case we are initialized on a non-main thread, make a best effort check before 335 // we return the scope. This is not sync but if developer is launching on a non-main 336 // dispatcher, they cannot be 100% sure anyways. 337 if (lifecycle.currentState == Lifecycle.State.DESTROYED) { 338 coroutineContext.cancel() 339 } 340 } 341 registernull342 fun register() { 343 launch(Dispatchers.Main.immediate) { 344 if (lifecycle.currentState >= Lifecycle.State.INITIALIZED) { 345 lifecycle.addObserver(this@LifecycleCoroutineScopeImpl) 346 } else { 347 coroutineContext.cancel() 348 } 349 } 350 } 351 onStateChangednull352 override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { 353 if (lifecycle.currentState <= Lifecycle.State.DESTROYED) { 354 lifecycle.removeObserver(this) 355 coroutineContext.cancel() 356 } 357 } 358 } 359 360 /** Creates a [Flow] of [Lifecycle.Event]s containing values dispatched by this [Lifecycle]. */ 361 public val Lifecycle.eventFlow: Flow<Lifecycle.Event> 362 get() = <lambda>null363 callbackFlow { 364 val observer = LifecycleEventObserver { _, event -> 365 trySend(event) 366 367 // Completes the producer if lifecycle is `DESTROYED`. 368 if (event == Lifecycle.Event.ON_DESTROY) { 369 close() 370 } 371 } 372 addObserver(observer) 373 awaitClose { removeObserver(observer) } 374 } 375 .flowOn(Dispatchers.Main.immediate) 376