【问题标题】:pass parameter to provider method when injecting the instance注入实例时将参数传递给提供者方法
【发布时间】:2017-10-02 09:45:15
【问题描述】:

我是 Dagger 2 的新手。我创建了一个模块,它有一个提供者方法,该方法接受一个字符串参数:

@Module
public class MyModule {

  @Provides
  Student provideStudent(String name) {
    return new Student(name); 
  }
}

在注入student的时候应该如何传递参数name@Inject Student student?但是在哪里/如何传递name

【问题讨论】:

  • 我应该如何在我想注入学生的消费者(活动/片段)中传递参数?你能详细说明一下吗?
  • 名字从何而来?
  • 从任何我想创建学生的地方。我的意思是我的项目可以在需要时创建一个学生实例,并硬编码名称。
  • 但最终活动/片段将打包?
  • 与你的问题无关,你应该看看 Constructor Injection,因为有了 Dagger,你不应该再调用 new 自己了。整个提供方法可以替换为单个@Inject,例如看这里:stackoverflow.com/a/45422229/1837367

标签: android dagger-2


【解决方案1】:

您希望将一个对象 (String name) 作为参数提供给您的组件,以便其他部分可以使用它。你基本上有两种选择。

模块构造函数参数

使用模块参数是您在引入Component.Builder 之前会使用的“经典”方法。

你所做的就是将你需要的东西添加到你的模块构造函数中,然后从模块中提供它。

@Module
public class MyModule {

  private String name;

  MyModule(String name) {
    this.name = name;
  }

  // -----------------------------------------------
  // you could obviously just use the field directly
  @Provides
  Student provideStudent() {
    return new Student(name); 
  }


  // ---------------------------------------------------------------------
  // alternatively you'd add a Qualifier and add the argument to the graph
  @Provides
  @Named("name")
  String provideName() {
    return name; 
  }

  // then you can use it...
  @Provides
  Student provideStudent(@Named("name") String name) {
    return new Student(name); 
  }

}

直接使用名称的第一个选项意味着它仅在 that 模块中可用。如果要使用构造函数注入或使用限定字符串,则必须将其添加到图中,如第二个所示。

使用任何一种方法,您都必须手动将模块添加到组件中,因为模块不再使用默认构造函数。这也是你现在提供论点的地方。

DaggerMyComponent.builder()
        .myModule(new MyModule("some name"))
        .build();

组件生成器

相同的概念但不同的方法是使用组件构建器来实现相同的目标——将某些东西绑定到图表。

@Component(modules = MyModule.class)
interface MyComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance Builder name(@Named("name") String name);

        MyComponent build();
    }
}

@Module
class MyModule {

    @Provides
    Student provideStudent(@Named("name") String name) {
        return new Student(name);
    }

}

在这里,您也只需将一个对象添加到可以使用的图表中。在这里,您也必须将其添加到组件构建器中

DaggerMyComponent.builder()
        .name("some name")
        .build();

【讨论】:

    【解决方案2】:

    您可以创建一个Student 工厂并注入它,而不是直接注入Student

    public class Student {
        public Student(String name, Knowledge knowledge) {}
    
        public static class Factory {
            private Knowledge knowledge;
    
            @Inject
            public Factory(Knowledge knowledge) {
                this.knowledge = knownledge;
            }
    
            public Student create(String name) {
                return new Student(name, knowledge);
            }
        }
    }
    

    或者 Kotlin 中的相同代码:

    class Student(name: String, knowledge: Knowledge) {
        class Factory @Inject constructor(private val knowledge: Knowledge) {
            fun create(name: String) = Student(name, knowledge)
        }
    }
    

    这允许在Student 实例化上传递name 参数,如下所示:

    public class MyClass {
        @Inject
        public Student.Factory studentFactory;
        private Student student;
    
        public void setupStudent() {
            this.student = studentFactory.create("Student's name");
        }
    }
    

    【讨论】:

      【解决方案3】:

      我的问题是如何注入一个有名字的学生实例可以 硬编码。

      nameStudent 的依赖关系,这个依赖关系是要解决的。为此,您需要一个带注释的@Provide 方法,该方法返回String。由于类型通常由返回类型推断,在String 的情况下,您还必须使用注释@Named

      @Provides
      @Named("Name")
      public String provideName() {
          return "My name";
      }
      

      然后改变你的方法

      @Provides
      Student provideStudent(@Named("Name") String name) {
         return new Student(name); 
      }
      

      这样 dagger2 知道如何解决 String 来构建 Student

      【讨论】:

      • 谢谢,但这还不足以回答我的问题,因为我在问如何在@Inject 阶段传递名称字符串,这是在消费阶段而不是提供阶段。您只在提供者(提供阶段)回答了如何做到这一点
      • to MyModule 你的意思是?
      • 例如在我的活动中,我需要一个学生实例,如何注入这样的实例?我的问题提到了@Inject Student student,但我如何在那里定义name?我想在消费阶段而不是提供阶段定义name。一般来说,我的 Activity/Fragment 想要注入一个学生实例,其名称可以是 Activity/Fragment 喜欢使用的任何名称。
      • 每次你开始你的activity/fragment,你都有一个不同的学生名字,你想让dagger2为你构建Student吗?抱歉,我无法理解您到底想要达到什么目的
      • 没有匕首 2,在 Activity 或任何需要学生实例的课程中,我做 Student student = new Student("Whatever name I want") ,用匕首 2,我做 @Inject Student student,但是如何在这里传递“我想要的任何名字”?那是我的问题。我不想在模块中定义名称,因为我希望那些需要学生定义名称的类。
      猜你喜欢
      • 1970-01-01
      • 2023-01-09
      • 2020-07-29
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2017-03-16
      • 2020-07-13
      相关资源
      最近更新 更多