1 /* 2 * 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 android.app.Activity 19 import android.app.Application 20 import android.content.Context 21 import android.os.Build 22 import android.os.Bundle 23 import android.os.Handler 24 import androidx.annotation.RequiresApi 25 import androidx.annotation.VisibleForTesting 26 import androidx.lifecycle.ReportFragment.Companion.reportFragment 27 28 /** 29 * Class that provides lifecycle for the whole application process. 30 * 31 * You can consider this LifecycleOwner as the composite of all of your Activities, except that 32 * [Lifecycle.Event.ON_CREATE] will be dispatched once and [Lifecycle.Event.ON_DESTROY] will never 33 * be dispatched. Other lifecycle events will be dispatched with following rules: 34 * ProcessLifecycleOwner will dispatch [Lifecycle.Event.ON_START], [Lifecycle.Event.ON_RESUME] 35 * events, as a first activity moves through these events. [Lifecycle.Event.ON_PAUSE], 36 * [Lifecycle.Event.ON_STOP], events will be dispatched with a **delay** after a last activity 37 * passed through them. This delay is long enough to guarantee that ProcessLifecycleOwner won't send 38 * any events if activities are destroyed and recreated due to a configuration change. 39 * 40 * It is useful for use cases where you would like to react on your app coming to the foreground or 41 * going to the background and you don't need a milliseconds accuracy in receiving lifecycle events. 42 */ 43 public class ProcessLifecycleOwner private constructor() : LifecycleOwner { 44 // ground truth counters 45 private var startedCounter = 0 46 private var resumedCounter = 0 47 private var pauseSent = true 48 private var stopSent = true 49 private var handler: Handler? = null 50 private val registry = LifecycleRegistry(this) <lambda>null51 private val delayedPauseRunnable = Runnable { 52 dispatchPauseIfNeeded() 53 dispatchStopIfNeeded() 54 } 55 private val initializationListener: ReportFragment.ActivityInitializationListener = 56 object : ReportFragment.ActivityInitializationListener { onCreatenull57 override fun onCreate() {} 58 onStartnull59 override fun onStart() { 60 activityStarted() 61 } 62 onResumenull63 override fun onResume() { 64 activityResumed() 65 } 66 } 67 68 public companion object { 69 @VisibleForTesting internal const val TIMEOUT_MS: Long = 700 // mls 70 private val newInstance = ProcessLifecycleOwner() 71 72 /** 73 * The LifecycleOwner for the whole application process. Note that if your application has 74 * multiple processes, this provider does not know about other processes. 75 * 76 * @return [LifecycleOwner] for the whole application. 77 */ 78 @JvmStatic getnull79 public fun get(): LifecycleOwner { 80 return newInstance 81 } 82 83 @JvmStatic initnull84 internal fun init(context: Context) { 85 newInstance.attach(context) 86 } 87 } 88 activityStartednull89 internal fun activityStarted() { 90 startedCounter++ 91 if (startedCounter == 1 && stopSent) { 92 registry.handleLifecycleEvent(Lifecycle.Event.ON_START) 93 stopSent = false 94 } 95 } 96 activityResumednull97 internal fun activityResumed() { 98 resumedCounter++ 99 if (resumedCounter == 1) { 100 if (pauseSent) { 101 registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) 102 pauseSent = false 103 } else { 104 handler!!.removeCallbacks(delayedPauseRunnable) 105 } 106 } 107 } 108 activityPausednull109 internal fun activityPaused() { 110 resumedCounter-- 111 if (resumedCounter == 0) { 112 handler!!.postDelayed(delayedPauseRunnable, TIMEOUT_MS) 113 } 114 } 115 activityStoppednull116 internal fun activityStopped() { 117 startedCounter-- 118 dispatchStopIfNeeded() 119 } 120 dispatchPauseIfNeedednull121 internal fun dispatchPauseIfNeeded() { 122 if (resumedCounter == 0) { 123 pauseSent = true 124 registry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE) 125 } 126 } 127 dispatchStopIfNeedednull128 internal fun dispatchStopIfNeeded() { 129 if (startedCounter == 0 && pauseSent) { 130 registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP) 131 stopSent = true 132 } 133 } 134 135 @Suppress("DEPRECATION") attachnull136 internal fun attach(context: Context) { 137 handler = Handler() 138 registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) 139 val app = context.applicationContext as Application 140 app.registerActivityLifecycleCallbacks( 141 object : EmptyActivityLifecycleCallbacks() { 142 @RequiresApi(29) 143 override fun onActivityPreCreated(activity: Activity, savedInstanceState: Bundle?) { 144 // We need the ProcessLifecycleOwner to get ON_START and ON_RESUME precisely 145 // before the first activity gets its LifecycleOwner started/resumed. 146 // The activity's LifecycleOwner gets started/resumed via an activity registered 147 // callback added in onCreate(). By adding our own activity registered callback 148 // in 149 // onActivityPreCreated(), we get our callbacks first while still having the 150 // right relative order compared to the Activity's onStart()/onResume() 151 // callbacks. 152 Api29Impl.registerActivityLifecycleCallbacks( 153 activity, 154 object : EmptyActivityLifecycleCallbacks() { 155 override fun onActivityPostStarted(activity: Activity) { 156 activityStarted() 157 } 158 159 override fun onActivityPostResumed(activity: Activity) { 160 activityResumed() 161 } 162 } 163 ) 164 } 165 166 override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { 167 // Only use ReportFragment pre API 29 - after that, we can use the 168 // onActivityPostStarted and onActivityPostResumed callbacks registered in 169 // onActivityPreCreated() 170 if (Build.VERSION.SDK_INT < 29) { 171 activity.reportFragment.setProcessListener(initializationListener) 172 } 173 } 174 175 override fun onActivityPaused(activity: Activity) { 176 activityPaused() 177 } 178 179 override fun onActivityStopped(activity: Activity) { 180 activityStopped() 181 } 182 } 183 ) 184 } 185 186 override val lifecycle: Lifecycle 187 get() = registry 188 189 @RequiresApi(29) 190 internal object Api29Impl { 191 @JvmStatic registerActivityLifecycleCallbacksnull192 fun registerActivityLifecycleCallbacks( 193 activity: Activity, 194 callback: Application.ActivityLifecycleCallbacks 195 ) { 196 activity.registerActivityLifecycleCallbacks(callback) 197 } 198 } 199 } 200