前面我们已经详细讲解过,如何通过 Component 和 Module 向 Activity 注入对象
这是基本的使用方法,它的缺点是当 Activity 特别多时,就需要非常多的 Component 和 Module 类
现在我们来讲解,如何通过 AndroidInjector 向基类进行统一注入
定义 DatabaseObject,可用依赖于不同对象,在不同 Activity 中有不同作用
public class DatabaseObject {
HomeActivity homeActivity;
SplashActivity splashActivity;
public DatabaseObject() {
}
public DatabaseObject(HomeActivity homeActivity) {
this.homeActivity = homeActivity;
}
public DatabaseObject(SplashActivity splashActivity) {
this.splashActivity = splashActivity;
}
}
定义 ApplicationComponent
@Component(modules = {
AndroidInjectionModule.class,
BaseActivityModule.class
})
public interface ApplicationComponent {
void inject(APP app);
}
定义 ApplicationComponent 的子组件
注意,这里的 Module 不同于常规的 Module,它并不用来提供对象,而是用来提供子组件的
Dagger 会根据每个@Contributes方法创建一个对应的SubComponent
@Module
public abstract class BaseActivityModule {
@ContributesAndroidInjector(modules = HomeActivityModule.class)
abstract HomeActivity contributesHomeActivity();
@ContributesAndroidInjector(modules = SplashActivityModule.class)
abstract SplashActivity contributesSplashActivity();
}
创建提供 Object 的 Module
DatabaseObject 依赖于 Activity,每个 Activity 的 Object 都是一个单独的实例,这种情景可用通过静态方法去创建
@Module
public class HomeActivityModule {
@Provides
static DatabaseObject provideDatabaseObject(HomeActivity homeActivity) {
return new DatabaseObject(homeActivity);
}
}
@Module
public class SplashActivityModule {
@Provides
static DatabaseObject provideDatabaseObject(SplashActivity splashActivity) {
return new DatabaseObject(splashActivity);
}
}
通过 ApplicationComponent 向 Application 注入 AndroidInjector
AndroidInjector 能够访问所有的 Component 和 Module,这样它就能自动帮助我们向 Activity 注入对象了
public class APP extends Application {
public static APP application;
ApplicationComponent applicationComponent;
@Inject
DispatchingAndroidInjector<Object> androidInjector;
@Override
public void onCreate() {
super.onCreate();
application = this;
applicationComponent = DaggerApplicationComponent.create();
applicationComponent.inject(this);
}
public static ApplicationComponent applicationComponent() {
return application.applicationComponent;
}
public static AndroidInjector<Object> androidInjector() {
return application.androidInjector;
}
}
通过 AndroidInjector 向 Activity 统一注入对象
AndroidInjector 会根据之类 Activity 的真实类名,来找到对应的 Component 和 Module,然后帮我们自动注入对象
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidInjector androidInjector = APP.application.androidInjector();
androidInjector.inject(this);
}
}
效果测试
@SuppressWarnings("all")
public class HomeActivity extends BaseActivity {
ActivityHomeBinding binding;
@Inject
DatabaseObject databaseObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHomeBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
test();
}
@Function
protected void test() {
System.err.println(databaseObject.hashCode());
}
@Override
public void onBackPressed() {
finish();
startActivity(new Intent(this, HomeActivity.class));
}
}
通过打印结果可以看到,对象确实注入成功了
只要我们在 BaseActivity 写一行注入代码,就可用为所有 Activity 自动注入对象
上面已经给出使用方法,下面我们再逐步讲解代码作用,以及 Dagger 是如何生成代码的
这里我没有给出完整的源码,而是将代码的核心流程概述出来
因为 Dagger 的代码量特别大,但是流程本身其实很简单,给出大量模版代码反而会影响大家去理解核心流程
ApplicationComponent依赖BaseActivityModule
BaseActivityModule中的每个@Contribute方法,都会对应生成一个SubActivityComponent类
BaseActivityModule中的每个@Contribute方法,都会对应生成一个SubActivityComponentFactory类
BaseActivityModule和AndroidInjector之所以能简化代码,是因为 Dagger 根据@Contribute方法自动帮我们生成了SubActivityComponent
实际上,这里的BaseActivityModule只是用来标记要生成哪些SubActivityComponent的,在源码中根本就没有用到它
如果我们需要向BaseActivity中统一注入其它对象,可以自己单独再创建一个 Module
整体的思路我们已经清楚了,是 Dagger 帮我们省略了许多的模版代码工作,现在我们开始理一下细节上是如何实现的
我们是统一通过 AndroidInjector 去注入的,实现的关键在于 AndroidInjector 如何提供 Activity
所有工作都是从ApplicationComponent开始的,而且它是单例的,所以任何对象都能拿到它的引用
ApplicationComponent依赖AndroidInjectionModule,这个 Dagger 内置 Module 可以帮我们注入AndroidInjector对象
ApplicationComponent在向 Application 注入AndroidInjector时,同时会将自己所有的SubComponentFactoryProvider全部传给AndroidInjector
因此AndroidInjector实际是通过ApplicationComponent::SubComponentFactoryProvider来提供 Activity 的
SubComponentFactoryProvider做的工作很简单,直接 new 一个SubComponentFactory
AndroidInjector向 Activity 注入对象时,实际是根据Activity::className找到对应的Provider,通过Provider创建Factory,通过Factory创建SubComponent,将当前 Activity 实例传给SubComponent,剩下的注入工作交给SubComponent就好了
以上是通过ApplicationComponent拿到SubComponent的过程,SubComponent拿到Object的流程大体相似,主要是通过Provider+Factory
AndroidInjector定义了一个 inject 方法,负责向AndroidTarget注入对象
AndroidInjector.Factory 定义了一个 create 方法,负责根据AndroidTarget创建 AndroidInjector
AndroidInjector 分为两种,一种是专门为绑定的AndroidTarget注入对象,一种是 DispatchingAndroidInjector,自身不负责注入对象,而是将注入工作分发给 SubAndroidInjector去处理
ApplicationComponent 内部包含了多个SubComponent.Factory,它们继承自 AndroidInjector.Factory接口,用于创建SubComponent
SubComponent实现了AndroidInjector接口,用于向绑定的 Activity 注入对象
SubComponent就是SubAndroidInjector,所以上一节中,Application::AndroidInjector的实际是在管理SubAndroidInjector
SubComponent内部持有了 Module 和 Activity,然后将这两个对象交给 ObjectFactory
ObjectFactory 会生成一个静态方法,该方法接受 Module 和 Activity 两个参数,然后调用 Module::staticProvide 方法来创建 Object