• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Dagger Authors.
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 dagger.hilt.android.internal.managers;
18 
19 import android.app.Activity;
20 import android.app.Application;
21 import androidx.activity.ComponentActivity;
22 import dagger.hilt.EntryPoint;
23 import dagger.hilt.EntryPoints;
24 import dagger.hilt.InstallIn;
25 import dagger.hilt.android.components.ActivityRetainedComponent;
26 import dagger.hilt.android.internal.builders.ActivityComponentBuilder;
27 import dagger.hilt.internal.GeneratedComponentManager;
28 
29 /**
30  * Do not use except in Hilt generated code!
31  *
32  * <p>A manager for the creation of components that live in the Activity.
33  *
34  * <p>Note: This class is not typed since its type in generated code is always <?> or <Object>. This
35  * is mainly due to the fact that we don't know the components at the time of generation, and
36  * because even the injector interface type is not a valid type if we have a hilt base class.
37  *
38  */
39 public class ActivityComponentManager
40     implements
41         GeneratedComponentManager<Object> {
42   /** Entrypoint for {@link ActivityComponentBuilder}. */
43   @EntryPoint
44   @InstallIn(ActivityRetainedComponent.class)
45   public interface ActivityComponentBuilderEntryPoint {
activityComponentBuilder()46     ActivityComponentBuilder activityComponentBuilder();
47   }
48 
49   private volatile Object component;
50   private final Object componentLock = new Object();
51 
52   protected final Activity activity;
53 
54   private final GeneratedComponentManager<ActivityRetainedComponent>
55       activityRetainedComponentManager;
56 
ActivityComponentManager(Activity activity)57   public ActivityComponentManager(Activity activity) {
58     this.activity = activity;
59     this.activityRetainedComponentManager =
60         new ActivityRetainedComponentManager((ComponentActivity) activity);
61   }
62 
63   @Override
generatedComponent()64   public Object generatedComponent() {
65     if (component == null) {
66       synchronized (componentLock) {
67         if (component == null) {
68           component = createComponent();
69         }
70       }
71     }
72     return component;
73   }
74 
getSavedStateHandleHolder()75   public final SavedStateHandleHolder getSavedStateHandleHolder() {
76     // This will only be used on base activity that extends ComponentActivity.
77     return ((ActivityRetainedComponentManager) activityRetainedComponentManager)
78         .getSavedStateHandleHolder();
79   }
80 
createComponent()81   protected Object createComponent() {
82     if (!(activity.getApplication() instanceof GeneratedComponentManager)) {
83       throw new IllegalStateException(
84           "Hilt Activity must be attached to an @HiltAndroidApp Application. "
85               + (Application.class.equals(activity.getApplication().getClass())
86                   ? "Did you forget to specify your Application's class name in your manifest's "
87                       + "<application />'s android:name attribute?"
88                   : "Found: " + activity.getApplication().getClass()));
89     }
90 
91     return EntryPoints.get(
92             activityRetainedComponentManager, ActivityComponentBuilderEntryPoint.class)
93         .activityComponentBuilder()
94         .activity(activity)
95         .build();
96   }
97 }
98