• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.android;
18 
19 import android.app.Application;
20 import android.content.ContentProvider;
21 import com.google.errorprone.annotations.ForOverride;
22 import dagger.internal.Beta;
23 import javax.inject.Inject;
24 
25 /**
26  * An {@link Application} that injects its members and can be used to inject objects that the
27  * Android framework instantiates, such as Activitys, Fragments, or Services. Injection is performed
28  * in {@link #onCreate()} or the first call to {@link AndroidInjection#inject(ContentProvider)},
29  * whichever happens first.
30  */
31 @Beta
32 public abstract class DaggerApplication extends Application implements HasAndroidInjector {
33   @Inject volatile DispatchingAndroidInjector<Object> androidInjector;
34 
35   @Override
onCreate()36   public void onCreate() {
37     super.onCreate();
38     injectIfNecessary();
39   }
40 
41   /**
42    * Implementations should return an {@link AndroidInjector} for the concrete {@link
43    * DaggerApplication}. Typically, that injector is a {@link dagger.Component}.
44    */
45   @ForOverride
applicationInjector()46   protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();
47 
48   /**
49    * Lazily injects the {@link DaggerApplication}'s members. Injection cannot be performed in {@link
50    * Application#onCreate()} since {@link android.content.ContentProvider}s' {@link
51    * android.content.ContentProvider#onCreate() onCreate()} method will be called first and might
52    * need injected members on the application. Injection is not performed in the constructor, as
53    * that may result in members-injection methods being called before the constructor has completed,
54    * allowing for a partially-constructed instance to escape.
55    */
injectIfNecessary()56   private void injectIfNecessary() {
57     if (androidInjector == null) {
58       synchronized (this) {
59         if (androidInjector == null) {
60           @SuppressWarnings("unchecked")
61           AndroidInjector<DaggerApplication> applicationInjector =
62               (AndroidInjector<DaggerApplication>) applicationInjector();
63           applicationInjector.inject(this);
64           if (androidInjector == null) {
65             throw new IllegalStateException(
66                 "The AndroidInjector returned from applicationInjector() did not inject the "
67                     + "DaggerApplication");
68           }
69         }
70       }
71     }
72   }
73 
74   @Override
androidInjector()75   public AndroidInjector<Object> androidInjector() {
76     // injectIfNecessary should already be called unless we are about to inject a ContentProvider,
77     // which can happen before Application.onCreate()
78     injectIfNecessary();
79 
80     return androidInjector;
81   }
82 }
83