当前位置: 首页 > 面试题库 >

如何在Android项目中从头开始设置DAGGER依赖项注入?

万俟渝
2023-03-14
问题内容

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

我想在我的Android项目中使用Dagger,但我感到困惑。

编辑:Dagger2也自2015年04月15日起退出市场,这更加令人困惑!

[[这个问题是一个“存根”,随着我对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提供接口以获取可注射类的类。

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以在生成的组件内获取作用域提供者,否则它将不受作用域的影响,并且每次注入时都会获得一个新实例。

3.2。)创建一个应用程序范围的组件,该组件指定您可以注入的内容(与injects={MainActivity.class}Dagger 1.x中的相同):

@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构造函数,则可以使用字段注入而不必显式调用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。)在为给定的接口定义了特定的实现之后,如下所示:

public interface Something {
    void doSomething();
}

@Singleton
public class SomethingImpl {
    @Inject
    AnotherThing anotherThing;

    @Inject
    public SomethingImpl() {
    }
}

您需要使用来将特定的实现“绑定”到接口@Module。

@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)

(注意:使用APTRebuild Project创建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课程

public class CustomApplication
        extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Injector.initialize(this);
    }
}

6.)添加CustomApplication到您的中AndroidManifest.xml。

<application
    android:name=".CustomApplication"
    ...

7.)将您的课程注入MainActivity

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为自己的组件指定创建活动级别范围的组件。子范围允许您提供仅对给定子范围而不是整个应用程序都需要的依赖项。通常,每个活动都通过此设置获得其自己的模块。请注意,每个组件都有一个作用域提供者,这意味着为了保留该活动的实例,该组件本身必须在配置更改后仍然有效。例如,它可以通过onRetainCustomNonConfigurationInstance()或Mortar示波器生存。

有关订阅的更多信息,请参阅Google的指南。另外,请访问此站点以了解供应方法以及组件依赖项部分)和此处。

要创建自定义范围,必须指定范围限定符批注:

@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结构。

谢谢



 类似资料:
  • 我如何在一个Android Gradle项目中设置模块的依赖关系,在这个项目中,模块之间相互依赖,这样我就可以一次部署所有模块的新快照或发布版本的构建? 该项目的结构如下: 项目配置文件如下,仅显示相关部分(根据我的判断): 设置。分级: lib-help/gradle.properties: lib-help/build.gradle: 当我运行时,所有内容都编译得很好,并且上载文件被推送到正确

  • Gradle 项目可以通过多项目配置依赖于其它 Gradle 项目。通常使用多项目配置会将所有库项目(如 lib1、lib2)添加到指定的根项目(如 libraries)。例如,给定以下项目结构: MyProject/ + app/ + libraries/ + lib1/ + lib2/ 我们可以找出3个项目。Gradle 将会按照以下名字进行映射: :app :librar

  • 基本上,我的Android库项目中有一个名为的单例类。在项目中,我有一个名为的类,它是一个Dagger2模块,它提供了我的单例,如下所示。 现在,在我的实际应用程序中,我有以下组件。 因此这用于将注入到类中。它是这样做的。

  • 我们正在尝试使用java webstart开发一个打印应用程序。我们使用eclipse将jar创建为普通jar文件。我们的应用程序需要外部库来连接数据库、将数据转换为字节等。 我们以前可以通过将必要的JAR放入jre文件夹的/ext/目录来实现这一点。然而,这导致了与tomcat服务器的库冲突,所以我们希望避免这种方法。 我们还尝试将项目导出为可运行的jar,因为所需的库也已打包在jar中。但是当

  • 我想要添加此依赖项编译到我的Android studio项目中。 当将此添加到依赖项中并单击同步时,显示此错误:

  • 我使用Eclipse Jetty集成,并假设这将管理我的java ee依赖项,但似乎并非如此?我怎么设置? 我已经从市场上安装了Eclipse Jetty Integration V4.0。我设置了一个动态web项目。在没有任何java代码的情况下,这可以很好地工作。当我创建一个Jetty WebApp并运行它时,index.html显示得很好。 找不到这些依赖项。 我尝试将eclipse库添加到