首页 > 解决方案 > 带有异步调用的 Dagger 返回类型

问题描述

在使用利用回调的 3rd 方函数时,我试图返回指定的类型。我有一个界面

public interface AuthenticationService {
    AuthResult signInEmailPassword(String username, String password, AuthListener listener);
}

在实现接口时,我正在调用使用回调的 AWS Cognito 异步函数。

public class AwsCognitoAuthenticator implements AuthenticationService {
    @Override
    public AuthResult signUp(String givenName, String username, String password, final AuthListener listener) {
        userPool.signUpInBackground(username, password, userAttributes, null, signupCallback);
    --> return result from signupCallback;
    }
}

调用此方法(signUpInBackground)时如何仍然返回 AuthResult 的类型?(我不想将其更改为 void 以便我可以在界面上使用 dagger)。

编辑

我在匕首中尝试了许多不同的方法,但我的尝试都没有成功。我正在尝试将以下接口作为字段注入到活动中。

@Component(modules = LoginModule.class)
public interface AuthenticationService {
    void signUp(String givenName, String username, String password, AuthListener listener);
    void signInEmailPassword(String username, String password, AuthListener listener);
    void changePassword(String oldPassword, String newPassword);
    void resetPassword();
    void signOut();
}

模块

@Module
public class LoginModule {
    @Provides
    AuthenticationService provideAuthService() {
        return new AwsCognitoAuthenticator();
    }
}

然后我得到三个在接口中有参数的声明的错误说

错误:此方法不是有效的提供方法、成员注入方法或子组件工厂方法。Dagger 无法实现此方法

标签: javaandroiddagger-2

解决方案


你不应该注释你用@Component. @Component具体来说,是指定义您希望 Dagger 为您实现的绑定图的接口。

@Component(modules = LoginModule.class)
public interface AuthenticationComponent {
  AuthenticationService getAuthenticationService();
}

上面的代码告诉 Dagger 使用@Module你列出的类和@Inject它找到的带注释的构造函数来创建你在组件上列出的类。在这里,该类是 AuthenticationService,根据您的 LoginModule,您将获得一个具体的 AwsCognitoAuthenticator。Dagger 在 AuthenticationComponent 附近生成此实现,以便您可以调用create为您完全创建的 AuthenticationService 获取工厂:

AuthenticationComponent authComponent = DaggerAuthenticationComponent.create();

因为你有一个绑定并且它所做的只是手动调用一个构造函数,所以你不会从 Dagger 中获得很多好处。但是,如果您的图表随着时间的推移而增长,或者如果您将 AwsCognitoAuthenticator 更改为需要其他依赖项,则这很容易影响其权重。


现在 Dagger 没有参与到你的 AuthenticationService 接口设计中,你可以专注于制作一个干净的 API。首先,您需要决定 AuthenticationService 的行为是同步的还是异步的。如果您要返回 AuthResult,则需要创建它,因此您似乎需要同步行为。也就是说,由于您接受 AuthListener,您似乎已经为异步行为做好了准备。作为您的 API 的消费者,我不明白这一点。请尝试以下方法之一:

  • 为您的每个方法接受 AuthListener 并使用它来回调。然后就可以返回了void。大概您接受的 AuthListener 有一个方法可以在后台任务完成并且您知道结果时接受 AuthResult 。您的大多数方法都会返回void,因为通常没有 AuthResult 同步返回。

  • 返回 aListenableFuture<AuthResult>而不是 AuthResult。这意味着 API 的返回值是一个对象,当 AuthResult 准备好时,可以接受要调用的侦听器,因此您不再需要接受 AuthListener 作为参数。这稍微贵一些,因为 ListenableFuture 需要数据结构来接受任意数量的侦听器,但它可能组合得更好(例如,如果您需要同时侦听多个 ListenableFuture 实例)。

  • 加倍使用同步 API,这样您的 AuthenticationService 方法在后台任务完成之前不会返回。在大多数情况下,这是一个坏主意,但这是可能的,然后您可以确保在需要返回时立即获得 AuthResult。


推荐阅读