android - Dagger 2 : inject after define subcomponent

标签 android dagger-2

我关注这个guide为我的 Android 应用程序制作子组件。这里我定义了一个名为 LoginComponent 的子组件用于 LoginActivity:

@Subcomponent(modules = LoginModule.class)
public interface LoginComponent {

    void inject(LoginActivity activity);

    @Subcomponent.Builder
    interface Builder {
        Builder requestModule(LoginModule module);
        LoginComponent build();
    }
}


@Module
public class LoginModule {
    @Provides
    LoginManager provideLoginManager(LoginManagerImpl manager) {
        return manager;
    }

    @Provides
    LoginView provideLoginView(LoginViewImpl view) {
        return view;
    }

    @Provides
    LoginPresenter loginPresenter(LoginView view, LoginManager manager) {
        return new LoginPresenterImpl(view, manager);
    }
}

我在另一个组件中定义了这个子组件:

@Module(subcomponents = LoginComponent.class)
public interface AppModule {
}

@Singleton
@Component(modules = {
        AppModule.class
})
public interface AppComponent {
}

这是我的登录 Activity :

public class LoginActivity extends AppCompatActivity  {

    @Inject LoginPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    }
}

我的问题是:

  1. @Subcomponent.Builder 的目的。我不明白这一点,因为该组件中的所有模块都已定义在 @Subcomponent 注解上。我们为什么要再次复制。
  2. 如何在上述 Activity 中注入(inject) LoginPresenter。

谢谢

最佳答案

  1. @Subcomponent.Builder遵循 @Component.Builder 中记录的相同规则:您需要为 Dagger 无法自行初始化的每个模块设置一个 setter。 (允许模块具有构造函数参数或静态工厂方法,这将阻止 Dagger 创建自己的实例。)

    因为 Dagger 可以通过调用零参数构造函数来创建 LoginModule,所以您可以从 Builder 中删除该方法;你不需要重新创建它。您也可以考虑制作 LoginModule 的方法 static ,这将允许您使 LoginModule 成为一个接口(interface)或抽象类——然后 Dagger 将能够完全避免持有对该模块的引用。最后,对于简单的 @Provides绑定(bind)两个类的方法(例如 @Provides B provideB(A a) { return a; } )你可以切换到 @Binds ,这将使生成的代码更快。

    那时,您的 @Subcomponent.Builder成为特定于子组件的 Provider : 你可以注入(inject)你的 BuilderProvider<Builder>并通过调用 build() 获取一个新的子组件实例在上面。只要您不需要提供任何 Module 实例,您就不需要在构建器上使用任何其他方法。

    您可以简单地注入(inject)一个 Provider<LoginComponent> ,但我没有在实践中看到过,也没有自己尝试过。

  2. 要注入(inject)一个 LoginPresenter,您需要获取您的 AppComponent,创建一个新的 LoginComponent,并通过传入它来使用它来注入(inject)您的 Activity。但是,这可能很困难,因为您还没有给自己任何注入(inject)您的 LoginComponent.Builder 的权限。

    除非你想尝试 dagger.android相反,您可以添加一个方法来调用您的 AppComponent 以创建一个新的 LoginComponent。

    // This way...
    LoginComponent createLoginComponent();
    
    // or this way:
    LoginComponent.Builder createLoginComponentBuilder();
    

    有时您会看到名为 plus() 的第一个方法,这是 Dagger 1 中建立的命名约定;第一种方法还可以让您避免创建 @Subcomponent.Builder 或在 AppModule 中添加子组件。 ,尽管您可能希望保留现有结构的结构,以便稍后向您的 AppModule 添加更多内容。

    要完成它,请在 Activity.onCreate 中,您可以让您的 Activity 获取您的应用程序,访问其 AppComponent,并注入(inject)自身。

    ((YourApplication) getContext().getApplicationContext())
        .getApp()
        .createLoginComponent()
        .inject(this);
    

关于android - Dagger 2 : inject after define subcomponent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43214994/

相关文章:

android - 三星 S6 上的 UnsatisfiedLinkError

android - 应用程序没有实现 dagger.android.HasDispatchingActivityInjector

android - 如何在模块中添加 View 模型?

android - 使用 Dagger 2 + Kotlin + ViewModel 注入(inject) ViewModel

android - 谷歌播放 : Does Beta Tester See Alpha Updates?

android - 从 uri 中检索位图

java - AlarmManager 没有触发我的服务

Android 可搜索配置未附加到 SearchView

java - dagger2如何注入(inject)不同作用域的同一类的对象?

java - Dagger 2 多重绑定(bind)教程的@AutoAnnotation 不起作用。如何让它发挥作用?