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 
17 package androidx.lifecycle;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 import android.os.Handler;
22 
23 import androidx.annotation.NonNull;
24 
25 /**
26  * Helper class to dispatch lifecycle events for a service. Use it only if it is impossible
27  * to use {@link LifecycleService}.
28  */
29 @SuppressWarnings("WeakerAccess")
30 public class ServiceLifecycleDispatcher {
31     private final LifecycleRegistry mRegistry;
32     private final Handler mHandler;
33     private DispatchRunnable mLastDispatchRunnable;
34 
35     /**
36      * @param provider {@link LifecycleOwner} for a service, usually it is a service itself
37      */
ServiceLifecycleDispatcher(@onNull LifecycleOwner provider)38     public ServiceLifecycleDispatcher(@NonNull LifecycleOwner provider) {
39         mRegistry = new LifecycleRegistry(provider);
40         mHandler = new Handler();
41     }
42 
postDispatchRunnable(Lifecycle.Event event)43     private void postDispatchRunnable(Lifecycle.Event event) {
44         if (mLastDispatchRunnable != null) {
45             mLastDispatchRunnable.run();
46         }
47         mLastDispatchRunnable = new DispatchRunnable(mRegistry, event);
48         mHandler.postAtFrontOfQueue(mLastDispatchRunnable);
49     }
50 
51     /**
52      * Must be a first call in {@link Service#onCreate()} method, even before super.onCreate call.
53      */
onServicePreSuperOnCreate()54     public void onServicePreSuperOnCreate() {
55         postDispatchRunnable(Lifecycle.Event.ON_CREATE);
56     }
57 
58     /**
59      * Must be a first call in {@link Service#onBind(Intent)} method, even before super.onBind
60      * call.
61      */
onServicePreSuperOnBind()62     public void onServicePreSuperOnBind() {
63         postDispatchRunnable(Lifecycle.Event.ON_START);
64     }
65 
66     /**
67      * Must be a first call in {@link Service#onStart(Intent, int)} or
68      * {@link Service#onStartCommand(Intent, int, int)} methods, even before
69      * a corresponding super call.
70      */
onServicePreSuperOnStart()71     public void onServicePreSuperOnStart() {
72         postDispatchRunnable(Lifecycle.Event.ON_START);
73     }
74 
75     /**
76      * Must be a first call in {@link Service#onDestroy()} method, even before super.OnDestroy
77      * call.
78      */
onServicePreSuperOnDestroy()79     public void onServicePreSuperOnDestroy() {
80         postDispatchRunnable(Lifecycle.Event.ON_STOP);
81         postDispatchRunnable(Lifecycle.Event.ON_DESTROY);
82     }
83 
84     /**
85      * @return {@link Lifecycle} for the given {@link LifecycleOwner}
86      */
getLifecycle()87     public Lifecycle getLifecycle() {
88         return mRegistry;
89     }
90 
91     static class DispatchRunnable implements Runnable {
92         private final LifecycleRegistry mRegistry;
93         final Lifecycle.Event mEvent;
94         private boolean mWasExecuted = false;
95 
DispatchRunnable(@onNull LifecycleRegistry registry, Lifecycle.Event event)96         DispatchRunnable(@NonNull LifecycleRegistry registry, Lifecycle.Event event) {
97             mRegistry = registry;
98             mEvent = event;
99         }
100 
101         @Override
run()102         public void run() {
103             if (!mWasExecuted) {
104                 mRegistry.handleLifecycleEvent(mEvent);
105                 mWasExecuted = true;
106             }
107         }
108     }
109 }
110