📅  最后修改于: 2023-12-03 15:08:33.573000             🧑  作者: Mango
在 Android 项目中,为了提高代码可维护性和可测试性,我们经常使用依赖注入框架 Dagger。但是,在多模块项目中,如何正确地使用 Dagger 呢?本文将为你介绍如何在 Android 的多模块项目中使用 Dagger。
首先,在项目的 build.gradle 中引入 Dagger 的依赖:
dependencies {
implementation "com.google.dagger:dagger:2.x"
annotationProcessor "com.google.dagger:dagger-compiler:2.x"
}
其中,2.x 是 Dagger 的版本号,可以根据自己的需求进行修改。
在每个模块的 build.gradle 中,需要配置注解处理器,以便 Dagger 在编译时生成必要的代码:
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = ["dagger.module.package": project.ext.modulePackage]
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
annotationProcessor "com.google.dagger:dagger-compiler:2.x"
implementation "com.google.dagger:dagger-android:2.x"
implementation "com.google.dagger:dagger-android-support:2.x"
}
其中,project.ext.modulePackage 为模块的包名。
在每个模块中,都需要定义一个 Component 接口,并使用 @Component 注解标注。在多模块中,建议使用 @Component.Builder 注解定义一个 Builder 接口,以便在使用子组件时能够灵活地配置。例如:
@Singleton
@Component(modules = {ApplicationModule.class, DataAccessModule.class})
public interface ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
ApplicationComponent build();
}
void inject(MyApplication application);
DataRepository getDataRepository();
}
在 App、Activity 和 Fragment 中,需要定义子组件,并使用 @Inject 注解标注需要注入的对象。
public class MyApplication extends Application {
private ApplicationComponent applicationComponent;
protected ApplicationComponent createApplicationComponent() {
return DaggerApplicationComponent.builder()
.application(this)
.build();
}
public ApplicationComponent getApplicationComponent() {
if (applicationComponent == null) {
applicationComponent = createApplicationComponent();
}
return applicationComponent;
}
}
public class MainActivity extends AppCompatActivity {
@Inject
DataRepository dataRepository;
private ActivityComponent activityComponent;
protected ActivityComponent createActivityComponent() {
return DaggerActivityComponent.builder()
.applicationComponent(((MyApplication) getApplication()).getApplicationComponent())
.activityModule(new ActivityModule(this))
.build();
}
public ActivityComponent getActivityComponent() {
if (activityComponent == null) {
activityComponent = createActivityComponent();
}
return activityComponent;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
getActivityComponent().inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 使用 dataRepository
}
}
public class MainFragment extends Fragment {
@Inject
DataRepository dataRepository;
private FragmentComponent fragmentComponent;
protected FragmentComponent createFragmentComponent() {
return DaggerFragmentComponent.builder()
.applicationComponent(((MyApplication) getActivity().getApplication()).getApplicationComponent())
.fragmentModule(new FragmentModule(this))
.build();
}
public FragmentComponent getFragmentComponent() {
if (fragmentComponent == null) {
fragmentComponent = createFragmentComponent();
}
return fragmentComponent;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
getFragmentComponent().inject(this);
super.onCreate(savedInstanceState);
// 使用 dataRepository
}
}
在每个模块中,都需要定义一个 Module 类,用于提供需要注入的对象。例如:
@Module
public class DataAccessModule {
@Singleton
@Provides
DataRepository provideDataRepository() {
return new DataRepository();
}
}
在多模块中,如果存在两个或者以上相同类型的对象需要被注入,或者需要提供不同的实现时,可以使用 @Named 注解来区分。
例如,两个服务都实现了相同的接口,需要在不同的模块中使用:
@Module
public class MainModule {
...
@Provides
@Named("main")
IMyService provideMyService(MainService myService) {
return myService;
}
}
@Module
public class OtherModule {
...
@Provides
@Named("other")
IMyService provideMyService(OtherService otherService) {
return otherService;
}
}
使用时,需要通过 @Named 注解区分:
@Inject
@Named("main")
IMyService myService;
@Inject
@Named("other")
IMyService otherService;
在多模块项目中,依赖注入框架 Dagger 的使用与单模块项目类似,只需要对 Component 和 Module 进行正确的配置和使用即可。同时需要注意的是,不同模块之间的对象注入需要使用子组件的方式,通过根组件和子组件将不同模块的对象进行连接。