preface
In my last article, I took a detailed look at ButterKnife, the dependency injection framework in Android, and used it to help eliminate the hassle of repeatedly writing findViewById and setOnclickListener. As we all know, when the project is getting bigger and bigger, the call level between the classes will be deeper and deeper, and some classes are activities/fragments, and some are singletons, and their life cycle is not consistent, so the creation of these objects to deal with the dependency of each object and the task of the life cycle will be very heavy, therefore, To solve this problem, the Dagger2 was created. Dagger2 is heavier and sharper than the lightweight use of ButterKnife, with overall control and integrated management of almost all dependencies in a project. Binder’s ServiceManager ServiceManager manages all the services (bootstrap, core, and other services), while Dagger2 integrates the dependencies in the project. Here, I’ll explore the internal implementation of Dagger2 and see how it manages dependencies.
Like RxJava, Dagger2 is a multiplatform library. Since Dagger2 is a bit cumbersome to write in general, Google has introduced a Dagger.Android usage for Android. This article will explore the internal implementation mechanism of Dagger2 based on the source code of Dagger.Android.
First, prepare knowledge
Given that Dagger has a certain cost to get started, I’ll take you through the basics that this source code analysis might cover to make reading easier.
1. @ Inject
Telling the dagger field or class that requires dependency injection, then using the annotation where the dependency is required, the dagger automatically generates an instance of the constructor.
Get required dependencies:
- Global variable injection
- Methods to inject
Provide the required example:
- Constructor injection (if there are multiple constructors, only one can be annotated, otherwise the compilation will fail)
2. @ the Module
Class annotation, indicating that the method of this class provides a dependency, tells where the dagger can be found. Use it where @inject cannot provide dependencies, such as classes provided by third-party libraries, basic data types, etc., where the source code cannot be modified.
Note: Dagger2 looks for dependencies on the @Module annotated class first, and only looks for the @Inject constructor of the class if there are none
3, @ Singleton
Declare this a singleton. After ensuring that there is only one Component and no rebuilding () is done, the object will be initialized only once, and the same object will be injected each time thereafter, which is a built-in scope.
There may be some misunderstandings about @Singleton. Here are some more details:
- Singleton is a Singleton annotated in Java code, but it is a Singleton in the same Component as Scope. That is, if the Component build () method is called again, a different object will still be retrieved, even if the Singleton annotation is used.
- It shows that the **@Singleton annotation only declares that this is a Singleton to improve the readability of the code, when it is the Component** that controls the object lifecycle. In the same way, @ActivityScope and @ApplicationScope are only declarations. Component controls the life cycle of an object.
4, @ will
Used only in @Module to provide constructed instances. It is generally used with @singleton to provide external dependencies in the form of Singleton method, which is a way to replace @Inject annotation construction method.
Note:
- Methods that use @Providers should use provide as a prefix, and classes that use @Module should use Module as a suffix.
- If the @providers method or @Inject constructor has an argument, make sure that it can be retrieved by the dagger, for example through another @providers method or @Inject annotation constructor.
5, @ Component
@Component is the container steward for Dagger2. It has all the dependencies of @Inject and @Module. At the same time, it is a syringe for obtaining and providing needed dependencies. The bridge here is the bridge between @Inject and @Module (or @Inject constructor). You need to list the Module components of the response when you define them, and you can also use Dependencies to inherit the parent Component.
Component and Module differences:
Component is both a syringe and a container manager, while Module is a child of Component as a container manager, essentially a module used to provide dependencies.
6, @ the Scope
Annotation scope, through custom annotations to limit the scope of the object, improve readability.
There are two common usage scenarios for @scope:
- A mock Singleton represents a global Singleton associated with the Component lifecycle.
- Simulate local singletons, such as during login to logout login.
7, @ the Qualifier
Qualifier, which defines annotation classes for distinguishing different instances of classification. For example, two methods return different Person objects, such as Ming and Hua. To distinguish them, use the annotation class defined by @qualifier.
8 dependencies.
Use it to indicate that ChildComponent depends on FatherComponent, as shown below:
@Component(modules = ChildModule.class, dependencies = FatherComponent.class)
public interface ChildComponent {
...
}
Copy the code
9, @ SubComponent
Representation is a child @Component that encapsulates different parts of the application in place of @dependencies.
Having reviewed the basics of the Dagger2, it’s time to start the engine.
Two, simple example (fromAwesomeWanAndroid)
First, create a BaseActivityComponent Subcomponent:
@Subcomponent(modules = {AndroidInjectionModule.class})
public interface BaseActivityComponent extends AndroidInjector<BaseActivity> {
@Subcomponent.Builder
abstract class BaseBuilder extends AndroidInjector.Builder<BaseActivity>{
}
}
Copy the code
This must be annotated as @SubComponent.Builder to indicate that it is the inner class of the top-level @SubComponent. Androidinjector.builder’s generics specify BaseActivity, which means that every Activity that inherits from BaseActivity inherits from the same BaseActivityComponent.
2. Then create a public Module that will import the Subcomponent.
// 1 @Module(subcomponents = {BaseActivityComponent.class}) public abstract class AbstractAllActivityModule { @ContributesAndroidInjector(modules = MainActivityModule.class) abstract MainActivity contributesMainActivityInjector(); @ContributesAndroidInjector(modules = SplashActivityModule.class) abstract SplashActivity contributesSplashActivityInjector(); / / a series of corresponding Activity contributesxxxActivityInjector... }Copy the code
Subcomponents in note 1 to open all rely on to AbstractAllActivityModule said, using a Subcomponent of different parts of the important reasons is that it will apply encapsulation. The @AppComponent maintains shared data and objects, while the differences are maintained by the respective @SubComponent.
3. Next, configure the Application for the project.
public class WanAndroidApp extends Application implements HasActivityInjector { // 3 @Inject DispatchingAndroidInjector<Activity> mAndroidInjector; private static volatile AppComponent appComponent; @Override public void onCreate() { super.onCreate(); . // 1 appComponent = DaggerAppComponent.builder() .build(); // 2 appComponent.inject(this); . }... // 4 @Override public AndroidInjector<Activity> activityInjector() { return mAndroidInjector; }}Copy the code
First, in comment 1, we build the AppComponent implementation class DaggerAppComponent using the AppModule and httpModule modules. Here’s the AppComponent configuration code:
@Singleton @Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule.class, AbstractAllActivityModule.class, AbstractAllFragmentModule.class, AbstractAllDialogFragmentModule. Class}) public interface AppComponent {/ * * * * * @ param injection WanAndroidApp instance wanAndroidApp WanAndroidApp */ void inject(WanAndroidApp wanAndroidApp); . }Copy the code
As you can see, the AppComponent dependence AndroidInjectionModule module, it contains some basic configuration of binding Settings, such as activityInjectorFactories, fragmentInjectorFactories, etc., And more AndroidSupportInjectionModule module is obviously a supportFragmentInjectorFactories binding Settings, activityInjectorFactories content such as shown below:
@Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>> activityInjectorFactories(); @Multibinds abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> fragmentInjectorFactories(); . }Copy the code
And then, The following dependent AbstractAllActivityModule, AbstractAllFragmentModule, AbstractAllDialogFragmentModule is all for the project Activity, the unification of the fragments, DialogFragment provide abstract base class Module, Look at the configuration of the AbstractAllActivityModule here:
@Module(subcomponents = {BaseActivityComponent.class}) public abstract class AbstractAllActivityModule { @ContributesAndroidInjector(modules = MainActivityModule.class) abstract MainActivity contributesMainActivityInjector(); @ContributesAndroidInjector(modules = SplashActivityModule.class) abstract SplashActivity contributesSplashActivityInjector(); . }Copy the code
As you can see, under the project of all xxxActiviity have corresponding contributesxxxActivityInjector injection () method with examples. And notice the AbstractAllActivityModule this module relies on subcomponents for BaseActivityComponent, said earlier, Every Activity that inherits from BaseActivity inherits from the BaseActivityComponent subcomponent. Similarly, AbstractAllFragmentModule is similar with AbstractAllDialogFragmentModule implementation pattern, as shown below:
// 1 @Module(c = BaseFragmentComponent.class) public abstract class AbstractAllFragmentModule { @ContributesAndroidInjector(modules = CollectFragmentModule.class) abstract CollectFragment contributesCollectFragmentInject(); @ContributesAndroidInjector(modules = KnowledgeFragmentModule.class) abstract KnowledgeHierarchyFragment contributesKnowledgeHierarchyFragmentInject(); . } // 2 @Module(subcomponents = BaseDialogFragmentComponent.class) public abstract class AbstractAllDialogFragmentModule { @ContributesAndroidInjector(modules = SearchDialogFragmentModule.class) abstract SearchDialogFragment contributesSearchDialogFragmentInject(); @ContributesAndroidInjector(modules = UsageDialogFragmentModule.class) abstract UsageDialogFragment contributesUsageDialogFragmentInject(); }Copy the code
Notice the code in comments 1 and 2, AbstractAllFragmentModule and AbstractAllDialogFragmentModule subcomponents BaseFragmentComponent, BaseDialogFragmentComponen T, apparently, is the same as the child components BaseActivityComponent AbstractAllActivityModule, they are both as a general child components.
Then, return to the code in comment 2 under Application in our config project, where we use the Dagger object we build for the DaggerAppComponent in step 1 to inject the current Application instance and hand it to the Dagger dependency manager to manage. Finally, the mAndroidInjector object created inside Dagger2 gives an instance assignment at comment 3. At comment 4, implement the HasActivityInjector interface and override the activityInjector() method to return the mAndroidInjector object we got above. The mAndroidInjector here is a type of DispatchingAndroidInjector object, you can understand it like this: It can perform member injection of core members of the Android framework such as activities and fragments. Under our project will DispatchingAndroidInjector generic specified for the Application of Activity that it assume the dependence among all the members of the Activity of injection. So, how to specify a particular Activity can be incorporated into DispatchingAndroidInjector all this Activity depends on the main pocket? Then look at using Step 4.
4, finally, the target Activity into DispatchingAndroidInjector Activity depend on the distribution manager.
It’s as simple as configuring androidInjection.inject (this) before super.onCreate(savedInstanceState) of the target Activity’s onCreate() method as follows:
public abstract class BaseActivity<T extends AbstractPresenter> extends AbstractSimpleActivity implements AbstractView { . @Inject protected T mPresenter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); }... }Copy the code
The use of @inject indicates the need to Inject an mPresenter instance. Then we need to use @Inject on the constructor of the concrete Presenter class to provide an mPresenter instance based on the current constructor, as shown below:
public class MainPresenter extends BasePresenter<MainContract.View> implements MainContract.Presenter { ... @Inject MainPresenter(DataManager dataManager) { super(dataManager); this.mDataManager = dataManager; }... }Copy the code
From the usage flow above, there are three key core implementations that we need to know, as follows:
-
1, appComponent = DaggerAppComponent. Builder (). The build () this code construct DaggerAppComponent?
-
Appcomponent.inject (this) How does the mAndroidInjector instance get assigned to the current Application?
-
3, under the target Activity AndroidInjection. Inject (this) the code is how to incorporate the object of the current Activity depends on allocation of manager DispatchingAndroidInjector a bag?
Let’s explore them one by one
Third, DaggerAppComponent. Builder (). The build () is how to construct DaggerAppComponent?
First, we look at the DaggerAppComponent’s Builder () method:
public static Builder builder() {
return new Builder();
}
Copy the code
A static inner class object from The Builder is returned.
public static final class Builder {
private Builder() {}
...
}
Copy the code
It seems that the default constructor for Builder does nothing, so the real implementation must be in the Build () method of the Builder object, followed by the Build () method.
public static final class Builder { ... public AppComponent build() { return new DaggerAppComponent(this); }... }Copy the code
The newly created DaggerAppComponent object is returned directly in the Build () method of the Builder. Now, look at the constructor of DaggerAppComponent:
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
Copy the code
The Initialize method is called in the Constructor of the DaggerAppComponent. As the name suggests, this is where the project’s global dependencies are actually initialized.
private void initialize(final Builder builder) { // 1 this.mainActivitySubcomponentBuilderProvider = new Provider< AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent .Builder>() { @Override public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent .Builder get() { // 2 return new MainActivitySubcomponentBuilder(); }}; / / a series of xxxActivitySubcomponentBuilderProvider create assignment code block... }Copy the code
In comment 1, a new subcomponent constructor instance Provider of mainActivit is created. In 2 place, use an anonymous inner class way to rewrite the Provider of the get () method, which returns a newly created good MainActivitySubcomponentBuilder object. Obviously, it is the Subcomponent builder that creates the dependencies needed to manage MAinActivity. Next we focus to analyze MainActivitySubcomponentBuilder under the function of a class.
// 1 private final class MainActivitySubcomponentBuilder extends AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent .Builder { private MainActivity seedInstance; @Override public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent build() { if (seedInstance == null) { throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set"); } // 2 return new MainActivitySubcomponentImpl(this); } @Override public void seedInstance(MainActivity arg0) { // 3 this.seedInstance = Preconditions.checkNotNull(arg0); }}Copy the code
First of all, in comment 1, MainActivitySubcomponen MainActivitySubcomponentBuilder son inherited AbstractAllActivityModule_ContributesMainActivityInjector internal components T internal child component Builder class Builder, as shown below:
@Subcomponent(modules = MainActivityModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends
AndroidInjector.Builder<MainActivity> {}
}
Copy the code
AndroidInjector Class Builder AndroidInjector Class Builder AndroidInjector Class Builder AndroidInjector Class Builder
As the name implies, AndroidInjector is an Android injector that performs member injection for each of the specific subtypes, the core Android types Activity and Fragment.
Now let’s take a look at the internal implementation of AndroidInjector. The source code is as follows:
public interface AndroidInjector<T> { void inject(T instance); // 1 interface Factory<T> { AndroidInjector<T> create(T instance); } // 2 abstract class Builder<T> implements AndroidInjector.Factory<T> { @Override public final AndroidInjector<T> create(T instance) { seedInstance(instance); return build(); } @BindsInstance public abstract void seedInstance(T instance); public abstract AndroidInjector<T> build(); }}Copy the code
In note 1, the abstract factory model has been used to create an instance of AndroidInjector of a concrete Activity or Fragment type. At note 2, the Builder implements AndroidInjector.factory, which is a generic implementation of subcomponent.Builder. In the override create() method, The instance save seedInstance() and concrete Android core types are built.
Then, we went back to MainActivitySubcomponentBuilder class, you can see, it implements the AndroidInjector. The Builder seedInstance () and the build () method. In the annotations 3 first planted MainActivity instance, then built a MainActivitySubcomponentImpl at 2 object to return. We will look at how MainActivitySubcomponentImpl this class mPresenter dependency injection, related to the source code is as follows:
private final class MainActivitySubcomponentImpl
implements AbstractAllActivityModule_ContributesMainActivityInjector
.MainActivitySubcomponent {
private MainPresenter getMainPresenter() {
// 2
return MainPresenter_Factory.newMainPresenter(
DaggerAppComponent.this.provideDataManagerProvider.get());
}
@Override
public void inject(MainActivity arg0) {
// 1
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
// 3
BaseActivity_MembersInjector
.injectMPresenter(instance, getMainPresenter());
return instance;
}
Copy the code
In note 1, MainActivitySubcomponentImpl realized AndroidInjector interface inject () method, InjectMainActivity () first calls the getMainPresenter() method to create a new MainPresenter object from the MainPresenter_Factory factory class. Let’s look at the newMainPresenter() method of MainPresenter:
public static MainPresenter newMainPresenter(DataManager dataManager) {
return new MainPresenter(dataManager);
}
Copy the code
I’m just going to create a MainPresenter. Then we went back to MainActivitySubcomponentImpl kind comment 3, continue to call the BaseActivity_MembersInjector injectMPresenter () method, as the name implies, can guess, It is a BaseActivity member syringe, continuing inside injectMPresenter() :
public static <T extends AbstractPresenter> void injectMPresenter(
BaseActivity<T> instance, T mPresenter) {
instance.mPresenter = mPresenter;
}
Copy the code
As you can see, the required mPresenter instance is assigned directly to the BaseActivity mPresenter. Of course, this refers to the BaseActivity subclass MainActivity, and other xxxActivity dependency management mechanisms are the same.
How does appComponent.inject(this) assign an instance of mAndroidInjector to the current Application?
Let’s continue looking at the appComponent Inject () method:
@Override
public void inject(WanAndroidApp wanAndroidApp) {
injectWanAndroidApp(wanAndroidApp);
}
Copy the code
InjectWanAndroidApp () is called in the injectWanAndroidApp() method.
private WanAndroidApp injectWanAndroidApp(WanAndroidApp instance) {
WanAndroidApp_MembersInjector.injectMAndroidInjector(
instance,
getDispatchingAndroidInjectorOfActivity());
return instance;
}
Copy the code
First, perform getDispatchingAndroidInjectorOfActivity () method gets an Activity type DispatchingAndroidInjector objects, Continue to see getDispatchingAndroidInjectorOfActivity () method:
private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf());
}
Copy the code
In getDispatchingAndroidInjectorOfActivity () method, the first call getMapOfClassOfAndProviderOfFactoryOf () method, we see this method:
private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
getMapOfClassOfAndProviderOfFactoryOf() {
return MapBuilder
.<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
newMapBuilder(8)
.put(MainActivity.class, (Provider) mainActivitySubcomponentBuilderProvider)
.put(SplashActivity.class, (Provider) splashActivitySubcomponentBuilderProvider)
.put(ArticleDetailActivity.class,
(Provider) articleDetailActivitySubcomponentBuilderProvider)
.put(KnowledgeHierarchyDetailActivity.class,
(Provider) knowledgeHierarchyDetailActivitySubcomponentBuilderProvider)
.put(LoginActivity.class, (Provider) loginActivitySubcomponentBuilderProvider)
.put(RegisterActivity.class, (Provider) registerActivitySubcomponentBuilderProvider)
.put(AboutUsActivity.class, (Provider) aboutUsActivitySubcomponentBuilderProvider)
.put(SearchListActivity.class, (Provider) searchListActivitySubcomponentBuilderProvider)
.build();
}
Copy the code
As you can see, I’ve created a new MapBuilder for builder mode implementation, and I’ve set a fixed capacity of 8, Under the project USES the AndroidInjection. Inject 8 Activity (mActivity) method corresponding xxxActivitySubcomponentBuilderProvider saved.
We go back to getDispatchingAndroidInjectorOfActivity () method, Here to get the Map above container was introduced into the DispatchingAndroidInjector_Factory newDispatchingAndroidInjector () method, There should be new DispatchingAndroidInjector. Let’s click inside to see:
public static <T> DispatchingAndroidInjector<T> newDispatchingAndroidInjector(
Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
return new DispatchingAndroidInjector<T>(injectorFactories);
}
Copy the code
Here, so he has built a DispatchingAndroidInjector object. Continue to look at DispatchingAndroidInjector constructor:
@Inject
DispatchingAndroidInjector(
Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
this.injectorFactories = injectorFactories;
}
Copy the code
This simply saves the Map that was passed in.
We return to WanAndroidApp_MembersInjector injectMAndroidInjector () method, will get DispatchingAndroidInjector instance to above, InjectMAndroidInjector () continues with the injectMAndroidInjector() method:
public static void injectMAndroidInjector(
WanAndroidApp instance, DispatchingAndroidInjector<Activity> mAndroidInjector) {
instance.mAndroidInjector = mAndroidInjector;
}
Copy the code
As you can see, finally in the injectMAndroidInjector() method of WanAndroidApp_MembersInjector, Directly to the newly built good DispatchingAndroidInjector instance assigned to the mAndroidInjector WanAndroidApp.
Five, under the target Activity AndroidInjection. Inject (this) the code is how to incorporate the object of the current Activity depend on the distribution header DispatchingAndroidInjector the bag?
First, we see the AndroidInjection. Inject (this) method:
public static void inject(Activity activity) { checkNotNull(activity, "activity"); // 1 Application application = activity.getApplication(); if (! (application instanceof HasActivityInjector)) { throw new RuntimeException( String.format( "%s does not implement %s", application.getClass().getCanonicalName(), HasActivityInjector.class.getCanonicalName())); } // 2 AndroidInjector<Activity> activityInjector = ((HasActivityInjector) application).activityInjector(); checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass()); // 3 activityInjector.inject(activity);Copy the code
}
In comment 1, it checks whether the current application has implemented the HasActivityInjector interface and throws a RuntimeException if not. If you have, will continue to call at 2 application of activityInjector DispatchingAndroidInjector instance () method. Finally, in comment 3, the current activity instance is passed into the Inject () method of activityInjector. We continue to look at the Inject () method:
@Override
public void inject(T instance) {
boolean wasInjected = maybeInject(instance);
if (!wasInjected) {
throw new IllegalArgumentException(errorMessageSuggestions(instance));
}
}
Copy the code
DispatchingAndroidInjector inject () method, its role is to give the incoming instance instance members into execution. In this case, it’s the mPresenter global variable that assigns the created Presenter instance to the BaseActivity object. Inside the Inject() method, the maybeInject() method is called, and we continue to look at it:
@CanIgnoreReturnValue public boolean maybeInject(T instance) { // 1 Provider<AndroidInjector.Factory<? extends T>> factoryProvider = injectorFactories.get(instance.getClass()); if (factoryProvider == null) { return false; } @SuppressWarnings("unchecked") // 2 AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get(); try { // 3 AndroidInjector<T> injector = checkNotNull( factory.create(instance), "%s.create(I) should not return null.", factory.getClass()); // 4 injector.inject(instance); return true; } catch (ClassCastException e) { ... }}Copy the code
In comment 1, we get the factoryProvider object from the injectorFactories based on the current Activity instance. Here we see the factoryProvider for the MainActivity. The first question that we study the mainActivitySubcomponentBuilderProvider:
private void initialize(final Builder builder) { this.mainActivitySubcomponentBuilderProvider = new Provider< AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent .Builder>() { @Override public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent .Builder get() { return new MainActivitySubcomponentBuilder(); }}; . }Copy the code
In maybeInject () method of 2, call the mainActivitySubcomponentBuilderProvider the get () method gets a new MainActivitySubcomponentBuilder object. The create() method is implemented in the AndroidInjector internal class Builder as follows:
abstract class Builder<T> implements AndroidInjector.Factory<T> {
@Override
public final AndroidInjector<T> create(T instance) {
seedInstance(instance);
return build();
}
Copy the code
Now, I’m sure those of you who read the first question already know what’s going on. In the create () method, we first MainActivitySubcomponentBuilder seedInstance () will MainActivity instance injection, And then call it the build () method has built a MainActivitySubcomponentImpl instance to return.
Finally, in April, enforcing MainActivitySubcomponentImpl inject () method:
private final class MainActivitySubcomponentImpl
implements AbstractAllActivityModule_ContributesMainActivityInjector
.MainActivitySubcomponent {
private MainPresenter getMainPresenter() {
// 2
return MainPresenter_Factory.newMainPresenter(
DaggerAppComponent.this.provideDataManagerProvider.get());
}
@Override
public void inject(MainActivity arg0) {
// 1
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
// 3
BaseActivity_MembersInjector
.injectMPresenter(instance, getMainPresenter());
return instance;
}
Copy the code
The logic here was explained in detail at the end of question 1. Finally, the BaseActivity_MembersInjector injectMPresenter() method is called in comment 3:
public static <T extends AbstractPresenter> void injectMPresenter(
BaseActivity<T> instance, T mPresenter) {
instance.mPresenter = mPresenter;
}
Copy the code
This assigns the mPresenter object to the mPresenter global variable of the current Activity object. At this point, the Dagger.Android core source code analysis is complete.
Five, the summary
Dagger is a sharp global dependency injection management framework compared to ButterKnife. Dagger is mainly used to manage object dependencies and lifecycle. As the project gets bigger and bigger, the call level between classes gets deeper and deeper, and some classes are activities or fragments, some are singletons. And their life cycles are inconsistent, so the dependency and life cycle tasks of creating the desired objects can be onerous. Therefore, using Dagger greatly eases this effort. Although it is expensive to learn and requires some template classes to be written, the larger the project, the more worthwhile the Dagger is. The next article will be the end of the Android mainstream tripartite library source code analysis series, I will be the Android EventBus framework source code in-depth analysis, please look for ~
Reference links:
1, Dagger V2.1.5 source code
2. Android advanced Light
3, farewell to Dagger2 template code: DaggerAndroid principle analysis
4, Android Dagger2 from zero single row