标签: dagger

使用Dagger在构造函数上进行依赖注入

所以,我正在重新设计我的Android应用程序以使用Dagger.我的应用程序庞大而复杂,我最近遇到了以下情况:

对象A需要一个特殊的DebugLogger实例,这是一个完美的注入候选者.我可以通过A的构造函数注入它,而不是绕过记录器.这看起来像这样:

class A
{
    private DebugLogger logger;

    @Inject
    public A(DebugLogger logger)
    {
        this.logger = logger;
    }

    // Additional methods of A follow, etc.
}
Run Code Online (Sandbox Code Playgroud)

到目前为止这是有道理的.但是,A需要由另一个类B构造.必须构造A的多个实例,所以遵循Dagger的做事方式,我简单地将一个注入Provider<A>到B中:

class B
{
    private Provider<A> aFactory;

    @Inject
    public B(Provider<A> aFactory)
    {
        this.aFactory = aFactory;
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,到目前为止还不错.但等等,突然A需要额外的输入,例如一个称为"数量"的整数,这对于它的构造至关重要.现在,我的A构造函数需要如下所示:

@Inject
public A(DebugLogger logger, int amount)
{
...
}
Run Code Online (Sandbox Code Playgroud)

突然,这个新参数干扰了注射.而且,即使这确实有效,除非我弄错了,否则在从提供者检索新实例时我无法传递"金额".我可以在这里做几件事,我的问题是哪一个是最好的?

我可以通过添加一个setAmount()预期在构造函数之后调用的方法来重构A. 然而,这是丑陋的,因为它迫使我延迟A的构造直到"数量"被填入.如果我有两个这样的参数,"数量"和"频率",那么我将有两个安装者,这将意味着要么复杂的检查以确保在调用两个setter之后恢复A的构造,或者我将不得不在混合中添加第三个方法,如下所示:

(Somewhere in B):

A inst = aFactory.get();
inst.setAmount(5);
inst.setFrequency(7);
inst.doConstructionThatRequiresAmountAndFrequency();
Run Code Online (Sandbox Code Playgroud)

另一种选择是我不使用基于构造函数的注射并使用基于场的注射.但现在,我必须把我的田地公之于众.这对我来说并不合适,因为现在我有义务将我班级的内部数据透露给其他班级.

到目前为止,我能想到的唯一优雅的解决方案是为提供者使用基于字段的注入,如下所示:

class A
{
    @Inject
    public Provider<DebugLogger> loggerProvider; …
Run Code Online (Sandbox Code Playgroud)

android dependency-injection dagger

28
推荐指数
1
解决办法
1万
查看次数

如何使用Dagger为活动和片段以外的东西设置依赖注入?

我开始使用Dagger设置依赖注入,如下所示.因为我可能有错误,所以请鼓励我更正我的实施!该实现遵循项目提供的android-simple示例.在下面你可以看到我是如何成功添加依赖注入ActivitiesFragments.我现在试着保持简单,所以我决定将Timber注入Android的log util的记录器替换.

import android.app.Application;
import java.util.Arrays;
import java.util.List;
import dagger.ObjectGraph;
import com.example.debugging.LoggingModule;

public class ExampleApplication extends Application {

    private ObjectGraph mObjectGraph;

    protected List<Object> getModules() {
        return Arrays.asList(
                new AndroidModule(this),
                new ExampleModule(),
                new LoggingModule()
        );
    }

    private void createObjectGraphIfNeeded() {
        if (mObjectGraph == null) {
            Object[] modules = getModules().toArray();
            mObjectGraph = ObjectGraph.create(modules);
        }
    }

    public void inject(Object object) {
        createObjectGraphIfNeeded();
        mObjectGraph.inject(object);
    }
}
Run Code Online (Sandbox Code Playgroud)

到现在AndroidModule没有任何地方使用,但可能会有所帮助时,ContextLayoutInflater …

android dependency-injection android-contentprovider android-asynctask dagger

28
推荐指数
2
解决办法
3万
查看次数

更新到Kotlin 1.3.30会中断Dagger 2.21的构建

从Kotling 1.3.21更新到1.3.30后生成错误:

AppComponent.java:16: error: [Dagger/MissingBinding]    
   java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,
   javax.inject.Provider<androidx.lifecycle.ViewModel>> 
   cannot be provided without an @Provides-annotated method.
Run Code Online (Sandbox Code Playgroud)

在两个对Kotlin,Dagger和Architecture组件具有相似依赖性的不同项目上进行了复制。

我怀疑它与kotlin 1.3.30中的最近kapt更新有关:https ://blog.jetbrains.com/kotlin/2019/04/kotlin-1-3-30-released/

试图禁用/启用文章中的kapt选项,尝试了gradle clean,使缓存无效,没有任何帮助。只有降级到1.3.21项目才能成功构建。

android kotlin dagger dagger-2

28
推荐指数
1
解决办法
1588
查看次数

Dagger默认构造函数

我想让Dagger在我的项目上工作.

但是,在编译期间,我在其中一个类上遇到以下异常:

错误:Foo上没有可注射成员.你想添加一个注射构造函数吗?

但是,该类没有依赖关系,因此使用默认的no-arg构造函数:

public class Foo
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

我是否真的需要添加一个像下面这样的可注射无参数构造函数?

public class Foo
{
     @Inject
     public Foo()
     {
     }

     ....
}
Run Code Online (Sandbox Code Playgroud)

dagger

27
推荐指数
1
解决办法
4161
查看次数

匕首2 - 为什么这是一个依赖循环?

我正在尝试将应用程序Context注入其他两个对象,一个AuthManager和一个ApiClient.

它们都取决于所述的背景,并且ApiClient取决于AuthManager.为什么这是一个依赖循环,如果Context没有引用其他2?这可以解决吗?

编辑:这是一些代码

@Module
public class AppModule {

    private final Application application;

    public AppModule(Application application) {
        this.application = application;
    }

    @Provides @Singleton
    Context provideApplicationContext() {
         return this.application;
    }
}


@Module
public class NetworkModule {

    @Provides @Singleton
    public AuthManager providesAuthManager(AuthManager manager) {
        return manager;
    }

    @Provides @Singleton
    public ApiClient providesApiClient(ApiClientFactory factory) {
        return factory.create();
    }
}

@Singleton
@Component(modules = {AppModule.class, NetworkModule.class})
public interface ApplicationComponent {
    void inject(BaseActivity activity); …
Run Code Online (Sandbox Code Playgroud)

android dependency-injection dagger dagger-2

27
推荐指数
1
解决办法
1万
查看次数

摆脱Dagger 2警告"生成一个MembersInjector"

鉴于以下课程

abstract class AbstractClass {
    @Inject SomeDependency someDependency;
}

class SomeClass extends AbstractClass {
    @Inject AnotherDependency anotherDepenency;

    public void onCreate() {
        component = // Get component instance somehow
        component.inject(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

在Dagger 2中,当将依赖项注入到从包含依赖项的抽象基类扩展的类中时,Dagger Generating a MembersInjector for AbstractClass. Prefer to run the dagger processor over that class instead.在编译期间显示了该类型的警告.

但是,如果我重写/实现onCreate()AbstractClass并调用依赖注入有,也依赖someDependency将被注入这两次可能会导致意外的行为.一旦onCreate()AbstractClass和一次onCreate()SomeClass.

在防止重复注入依赖项的同时摆脱此警告的最佳解决方案是什么?

java dagger dagger-2

27
推荐指数
1
解决办法
1045
查看次数

无法解析变量'$ {project.groupId}'

我将项目迁移到AndroidX,在构建项目时遇到了这些错误:

[TAG] Failed to resolve variable '${project.groupId}'   
[TAG] Failed to resolve variable '${project.version}'   
[TAG] Failed to resolve variable '${project.groupId}'   
[TAG] Failed to resolve variable '${project.version}'   
[TAG] Failed to resolve variable '${project.groupId}'   
[TAG] Failed to resolve variable '${project.version}'   
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几种可能的解决方

  • 清洁项目
  • 使缓存无效并重新启动
  • 设为enableJetifierfalse
  • 添加--refresh-dependencies编译器设置选项

这是我的项目gradle文件:

buildscript {
    repositories {
        jcenter()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
        google()
        maven {
            url 'https://maven.fabric.io/public'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        classpath 'com.google.gms:google-services:4.0.0'
        classpath 'io.fabric.tools:gradle:1.25.4'
    }
}

allprojects { …
Run Code Online (Sandbox Code Playgroud)

android dagger android-gradle-plugin androidx

27
推荐指数
3
解决办法
1万
查看次数

我可以在Espresso中扩展自定义应用程序吗?

我正在尝试在Espresso仪器测试中设置Dagger,以模拟对外部资源的调用(在这种情况下为RESTful服务).我在Robolectric中为我的单元测试所遵循的模式是扩展我的生产Application类并使用将返回模拟的测试模块覆盖Dagger模块.我试图在这里做同样的事情,但是当我尝试将应用程序转换为我的自定义应用程序时,我在Espresso测试中遇到了ClassCastException.

这是我到目前为止的设置:

生产

在app/src/main/java/com/mypackage/injection下我有:

MyCustomApplication

package com.mypackage.injection;

import android.app.Application;

import java.util.ArrayList;
import java.util.List;

import dagger.ObjectGraph;

public class MyCustomApplication extends Application {

    protected ObjectGraph graph;

    @Override
    public void onCreate() {
        super.onCreate();

        graph = ObjectGraph.create(getModules().toArray());
    }

    protected List<Object> getModules() {
        List<Object> modules = new ArrayList<Object>();
        modules.add(new AndroidModule(this));
        modules.add(new RemoteResourcesModule(this));
        modules.add(new MyCustomModule());

        return modules;
    }

    public void inject(Object object) {
        graph.inject(object);
    }
}
Run Code Online (Sandbox Code Playgroud)

我用以下方式使用:

BaseActivity

package com.mypackage.injection.views;

import android.app.Activity;
import android.os.Bundle;

import com.mypackage.injection.MyCustomApplication;

public abstract class MyCustomBaseActivity extends Activity {

    @Override
    protected void …
Run Code Online (Sandbox Code Playgroud)

android dagger android-espresso

26
推荐指数
4
解决办法
8518
查看次数

Dagger + Retrofit.在运行时添加auth头

我想知道Dagger是否有办法知道它应该在新数据可用时重新创建一个对象.

我所说的实例是我用于改造的请求标题.在某些时候(当用户登录时),我得到一个令牌,我需要将其添加到改造的标题中以进行经过身份验证的请求.问题是,我留下了相同的未经验证的改造版本.这是我的注射代码:

@Provides
    @Singleton
    OkHttpClient provideOkHttpClient(Cache cache) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .cache(cache).build();
         client
                .newBuilder()
                .addInterceptor(
                    chain -> {
                        Request original = chain.request();
                        Request.Builder requestBuilder = original.newBuilder()
                                .addHeader("Accept", "Application/JSON");
                        Request request = requestBuilder.build();
                        return chain.proceed(request);
                    }).build();
        return client;
    }

  @Provides
    @Singleton
    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) { 
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
                .baseUrl(mBaseUrl)
                .client(okHttpClient)
                .build();
        return retrofit;
}

@Provides
    @Singleton
    public NetworkService providesNetworkService(Retrofit retrofit) {
        return retrofit.create(NetworkService.class);
    }
Run Code Online (Sandbox Code Playgroud)

关于如何使这项工作的任何想法?

java android dagger dagger-2 retrofit2

25
推荐指数
2
解决办法
9624
查看次数

指定注释处理器的顺序

我正在尝试在我的Java项目上运行Dagger 2和Lombok.当然,龙目岛必须首先运行,但实际上它是否真的有机会.起初我怀疑我可以通过类路径中库jar的相应位置来指定顺序,但是该顺序显然会被忽略.

有没有办法指定它们以某种方式运行的顺序,或者我只是不得不忍受不能组合两个AP?

我制作了一个SSCCE测试用例.

一个简单的git clone&mvn compile足以证明这个问题 - 如果您在App.java中注释第18行并取消注释第20-21行,它将进行编译,即使第18行中的Lombok表示法创建了相同的构造函数.问题是龙目岛似乎追随Dagger.

java annotation-processing lombok dagger

24
推荐指数
3
解决办法
6011
查看次数