📌  相关文章
📜  如何在 Android 的多模块项目中使用 Dagger?(1)

📅  最后修改于: 2023-12-03 15:08:33.573000             🧑  作者: Mango

如何在 Android 的多模块项目中使用 Dagger?

在 Android 项目中,为了提高代码可维护性和可测试性,我们经常使用依赖注入框架 Dagger。但是,在多模块项目中,如何正确地使用 Dagger 呢?本文将为你介绍如何在 Android 的多模块项目中使用 Dagger。

1. 配置 build.gradle

首先,在项目的 build.gradle 中引入 Dagger 的依赖:

dependencies {
  implementation "com.google.dagger:dagger:2.x"
  annotationProcessor "com.google.dagger:dagger-compiler:2.x"
}

其中,2.x 是 Dagger 的版本号,可以根据自己的需求进行修改。

2. 配置注解处理器

在每个模块的 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 为模块的包名。

3. 使用 @Component 注解

在每个模块中,都需要定义一个 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();
}
4. 定义 App、Activity 和 Fragment 的子组件

在 App、Activity 和 Fragment 中,需要定义子组件,并使用 @Inject 注解标注需要注入的对象。

  1. 在 App 中,定义一个 ApplicationComponent 作为根组件,并定义一个 createApplicationComponent 方法用于创建 ApplicationComponent。例如:
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;
    }
}
  1. 在 Activity 中,定义一个 ActivityComponent 子组件,并定义一个 createActivityComponent 方法用于创建 ActivityComponent。例如:
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
    }
}
  1. 在 Fragment 中,定义一个 FragmentComponent 子组件,并定义一个 createFragmentComponent 方法用于创建 FragmentComponent。例如:
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
    }
}
5. 定义 Module

在每个模块中,都需要定义一个 Module 类,用于提供需要注入的对象。例如:

@Module
public class DataAccessModule {

    @Singleton
    @Provides
    DataRepository provideDataRepository() {
        return new DataRepository();
    }

}
6. 使用 @Named 注解

在多模块中,如果存在两个或者以上相同类型的对象需要被注入,或者需要提供不同的实现时,可以使用 @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;
7. 总结

在多模块项目中,依赖注入框架 Dagger 的使用与单模块项目类似,只需要对 Component 和 Module 进行正确的配置和使用即可。同时需要注意的是,不同模块之间的对象注入需要使用子组件的方式,通过根组件和子组件将不同模块的对象进行连接。