gpt4 book ai didi

android - 如何在Android项目中从头开始设置DAGGER依赖注入(inject)?

转载 作者:IT老高 更新时间:2023-10-28 13:05:43 26 4
gpt4 key购买 nike

如何使用 Dagger ?如何配置 Dagger 以在我的 Android 项目中工作?

我想在我的 Android 项目中使用 Dagger,但我觉得它很困惑。

编辑:Dagger2 也从 2015 年 04 月 15 日开始发布,它更令人困惑!

[这个问题是一个“ stub ”,当我更多地了解 Dagger1 和更多地了解 Dagger2 时,我将添加到我的答案中。这个问题更像是一个 指南 而不是一个“问题”。]

最佳答案

指南 Dagger 2.x (修订版 6):

步骤如下:

1.) 添加 Dagger给您的 build.gradle文件:

  • 顶级 build.gradle :

  • .
    // Top-level build file where you can add configuration options common to all sub-projects/modules.

    buildscript {
    repositories {
    jcenter()
    }
    dependencies {
    classpath 'com.android.tools.build:gradle:2.2.0'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //added apt for source code generation
    }
    }

    allprojects {
    repositories {
    jcenter()
    }
    }
  • 应用级别 build.gradle :

  • .
    apply plugin: 'com.android.application'
    apply plugin: 'com.neenbedankt.android-apt' //needed for source code generation

    android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"

    defaultConfig {
    applicationId "your.app.id"
    minSdkVersion 14
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"
    }
    buildTypes {
    debug {
    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    release {
    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    }
    }

    dependencies {
    apt 'com.google.dagger:dagger-compiler:2.7' //needed for source code generation
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.google.dagger:dagger:2.7' //dagger itself
    provided 'org.glassfish:javax.annotation:10.0-b28' //needed to resolve compilation errors, thanks to tutplus.org for finding the dependency
    }

    2.) 创建您的 AppContextModule提供依赖的类。
    @Module //a module could also include other modules
    public class AppContextModule {
    private final CustomApplication application;

    public AppContextModule(CustomApplication application) {
    this.application = application;
    }

    @Provides
    public CustomApplication application() {
    return this.application;
    }

    @Provides
    public Context applicationContext() {
    return this.application;
    }

    @Provides
    public LocationManager locationService(Context context) {
    return (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    }
    }

    3.) 创建 AppContextComponent提供获取可注入(inject)类的接口(interface)的类。
    public interface AppContextComponent {
    CustomApplication application(); //provision method
    Context applicationContext(); //provision method
    LocationManager locationManager(); //provision method
    }

    3.1.) 这是创建具有实现的模块的方式:
    @Module //this is to show that you can include modules to one another
    public class AnotherModule {
    @Provides
    @Singleton
    public AnotherClass anotherClass() {
    return new AnotherClassImpl();
    }
    }

    @Module(includes=AnotherModule.class) //this is to show that you can include modules to one another
    public class OtherModule {
    @Provides
    @Singleton
    public OtherClass otherClass(AnotherClass anotherClass) {
    return new OtherClassImpl(anotherClass);
    }
    }

    public interface AnotherComponent {
    AnotherClass anotherClass();
    }

    public interface OtherComponent extends AnotherComponent {
    OtherClass otherClass();
    }

    @Component(modules={OtherModule.class})
    @Singleton
    public interface ApplicationComponent extends OtherComponent {
    void inject(MainActivity mainActivity);
    }

    当心: : 您需要提供 @Scope模块的 @Singleton 上的注释(如 @ActivityScope@Provides )带注释的方法在生成的组件中获取作用域提供程序,否则它将是无作用域的,并且每次注入(inject)时都会获得一个新实例。

    3.2.) 创建一个应用程序范围的组件,指定您可以注入(inject)的内容(这与 Dagger 1.x 中的 injects={MainActivity.class} 相同):
    @Singleton
    @Component(module={AppContextModule.class}) //this is where you would add additional modules, and a dependency if you want to subscope
    public interface ApplicationComponent extends AppContextComponent { //extend to have the provision methods
    void inject(MainActivity mainActivity);
    }

    3.3.) 对于您可以自己通过构造函数创建并且不想使用 @Module 重新定义的依赖项(例如,您使用构建风格来更改实现类型),您可以使用 @Inject带注释的构造函数。
    public class Something {
    OtherThing otherThing;

    @Inject
    public Something(OtherThing otherThing) {
    this.otherThing = otherThing;
    }
    }

    另外,如果您使用 @Inject构造函数,您可以使用字段注入(inject)而无需显式调用 component.inject(this) :
    public class Something {
    @Inject
    OtherThing otherThing;

    @Inject
    public Something() {
    }
    }

    这些 @Inject构造函数类会自动添加到相同作用域的组件中,而无需在模块中显式指定它们。

    一个 @Singleton范围 @Inject构造函数类将在 @Singleton 中看到作用域组件。
    @Singleton // scoping
    public class Something {
    OtherThing otherThing;

    @Inject
    public Something(OtherThing otherThing) {
    this.otherThing = otherThing;
    }
    }

    3.4.) 在为给定接口(interface)定义特定实现后,如下所示:
    public interface Something {
    void doSomething();
    }

    @Singleton
    public class SomethingImpl {
    @Inject
    AnotherThing anotherThing;

    @Inject
    public SomethingImpl() {
    }
    }

    您需要使用 @Module 将特定实现“绑定(bind)”到接口(interface)。 .
    @Module
    public class SomethingModule {
    @Provides
    Something something(SomethingImpl something) {
    return something;
    }
    }

    自 Dagger 2.4 以来,对此的简写如下:
    @Module
    public abstract class SomethingModule {
    @Binds
    abstract Something something(SomethingImpl something);
    }

    4.) 创建一个 Injector类来处理您的应用程序级组件(它取代了整体 ObjectGraph)

    (注意: Rebuild Project 使用 APT 创建 DaggerApplicationComponent 构建器类)
    public enum Injector {
    INSTANCE;

    ApplicationComponent applicationComponent;

    private Injector(){
    }

    static void initialize(CustomApplication customApplication) {
    ApplicationComponent applicationComponent = DaggerApplicationComponent.builder()
    .appContextModule(new AppContextModule(customApplication))
    .build();
    INSTANCE.applicationComponent = applicationComponent;
    }

    public static ApplicationComponent get() {
    return INSTANCE.applicationComponent;
    }
    }

    5.) 创建您的 CustomApplication类(class)
    public class CustomApplication
    extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    Injector.initialize(this);
    }
    }

    6.) 添加 CustomApplication给您的 AndroidManifest.xml .
    <application
    android:name=".CustomApplication"
    ...

    7.) MainActivity 中注入(inject)您的类(class)
    public class MainActivity
    extends AppCompatActivity {
    @Inject
    CustomApplication customApplication;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Injector.get().inject(this);
    //customApplication is injected from component
    }
    }

    8.) 享受!

    +1。) 您可以指定 Scope用于您可以创建的组件 Activity 级范围组件 .子作用域允许您提供仅对给定子作用域而不是在整个应用程序中需要的依赖项。通常,每个 Activity 都会通过此设置获得自己的模块。请注意存在范围内的提供者 每个组件 ,这意味着为了保留该 Activity 的实例,组件本身必须在配置更改后幸免于难。例如,它可以通过 onRetainCustomNonConfigurationInstance() 存活下来。 ,或迫击炮瞄准镜。

    有关子范围划分的更多信息,请查看 the guide by Google .另请参阅 this site about provision methods还有 component dependencies section ) 和 here .

    要创建自定义范围,您必须指定范围限定符注释:
    @Scope
    @Retention(RetentionPolicy.RUNTIME)
    public @interface YourCustomScope {
    }

    要创建子作用域,您需要在组件上指定作用域,并指定 ApplicationComponent作为它的依赖。显然,您还需要在模块提供程序方法上指定子范围。
    @YourCustomScope
    @Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
    public interface YourCustomScopedComponent
    extends ApplicationComponent {
    CustomScopeClass customScopeClass();

    void inject(YourScopedClass scopedClass);
    }

    并且
    @Module
    public class CustomScopeModule {
    @Provides
    @YourCustomScope
    public CustomScopeClass customScopeClass() {
    return new CustomScopeClassImpl();
    }
    }

    请注意只有 可以将作用域组件指定为依赖项。想想它就像 Java 中不支持多重继承一样。

    +2.) 关于 @Subcomponent :本质上,一个范围 @Subcomponent可以替换一个组件依赖;但不是使用注释处理器提供的构建器,您需要使用组件工厂方法。

    所以这个:
    @Singleton
    @Component
    public interface ApplicationComponent {
    }

    @YourCustomScope
    @Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class})
    public interface YourCustomScopedComponent
    extends ApplicationComponent {
    CustomScopeClass customScopeClass();

    void inject(YourScopedClass scopedClass);
    }

    变成这样:
    @Singleton
    @Component
    public interface ApplicationComponent {
    YourCustomScopedComponent newYourCustomScopedComponent(CustomScopeModule customScopeModule);
    }

    @Subcomponent(modules={CustomScopeModule.class})
    @YourCustomScope
    public interface YourCustomScopedComponent {
    CustomScopeClass customScopeClass();
    }

    而这个:
    DaggerYourCustomScopedComponent.builder()
    .applicationComponent(Injector.get())
    .customScopeModule(new CustomScopeModule())
    .build();

    变成这样:
    Injector.INSTANCE.newYourCustomScopedComponent(new CustomScopeModule());

    +3.): 请检查其他有关 Dagger2 的 Stack Overflow 问题,它们提供了很多信息。例如,我当前的 Dagger2 结构在 this answer 中指定.

    感谢

    感谢您在 Github 的指导, TutsPlus , Joe Steele , Froger MCSGoogle .

    也是为了这个 step by step migration guide I found after writing this post.

    而对于 scope explanation通过基里尔。

    更多信息请见 official documentation .

    关于android - 如何在Android项目中从头开始设置DAGGER依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27036933/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com