Dagger - 从其他 class 访问单例对象

Dagger - Accessing Singleton object from other class

我一直在努力理解和设置 Dagger 来处理我的 Android 项目的依赖注入。我的单例(没有双关语意)objective 是创建我可以在我的应用程序中访问的单例对象。我已经成功地设置了初始 activity 中的对象。我被卡住的地方是从其他 classes 访问这些对象。到目前为止,这是我的设置:

初始应用程序Activity

public class SplashScreenActivity extends AppCompatActivity {

    @Inject SessionKeyExchangerService exchangerService;

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

        AppComponent component = DaggerAppComponent.builder().appModule(new AppModule()).build();

        // establish the session id as a singleton object
        exchangerService = component.provideSessionKeyExchangerService();

        // test whether I can access the singleton from another class
        exchangerService.sendEncryptedKeyToServer();
    } 

组件Class

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

    SessionKeyExchangerService provideSessionKeyExchangerService();

    AESCipherService provideCipherService();
}

模块Class

@Module
public class AppModule {

    @Provides @Singleton
    AESCipherService provideCipherService() {
        return new AESCipherService();
    }

    @Provides @Singleton
    SessionKeyExchangerService provideSessionKeyExchangerService(AESCipherService service) {
        return new SessionKeyExchangerService(service);
    }
}

AESCipherService

public class AESCipherService {

    private Long sessionId;

    public AESCipherService() {
        sessionId = makeSessionId();
        Log.d(Constants.TAG, "Session ID: " + Long.toString(sessionId));
    }

    private Long makeSessionId() {
        // this generates a random unsigned integer in the space {0, 2^32-1)
        Random random = new Random();
        return random.nextLong() & 0xffffffffL;
    }

    public Long getSessionId() {
        return sessionId;
    }
}

会话密钥交换器Class

public class SessionKeyExchangerService {

    private static SessionKeyExchangerService exchanger;
    private AESCipherService cipherService;

    @Inject
    public SessionKeyExchangerService(AESCipherService cipherService) {
        this.cipherService = cipherService;
    }

    public void sendEncryptedKeyToServer () {

        // the next line is almost certainly part of the problem
        // but I don't know how to fix!!!
        AppComponent component = DaggerAppComponent.builder().appModule(new AppModule()).build();

        AESCipherService cipherService = component.provideCipherService();

        Long sessionID = cipherService.getSessionId();
        Log.d(Constants.TAG, "singleton verification: " + (Long.toString(sessionID)));
    }

这是一些示例输出:

Session ID: 217186720
singleton verification: 790090968

很明显,我访问的不是同一个对象。我意识到问题的至少一部分源于我在 AESCipherService 中调用 new 运算符的方式,当我试图获取对 AppComponent [= 的引用时55=],但我不知道如何以任何其他方式获取此引用。

我该如何解决这个问题?谢谢!

 AppComponent component = DaggerAppComponent.builder().appModule(new AppModule()).build();

不不不不不不。那不会是单身人士。 Scoped providers 仅针对每个组件工作,这意味着您必须在整个应用程序中使用单个组件才能拥有 @Singleton 个实际上共享相同范围提供程序的范围模块。在这种情况下,每次创建 activity 时都会创建一个新组件。

您需要像这样创建它们:

public enum Injector {
    INSTANCE;

    private AppComponent appComponent;

    static {
        INSTANCE.appComponent = DaggerAppComponent.create();
    }

    public getAppComponent() {
        return appComponent;
    }
}

您也可以子类化 Application 并在 onCreate() 中创建一个。

还有

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
    SessionKeyExchangerService provideSessionKeyExchangerService();
    AESCipherService provideCipherService();

    void inject(SplashScreenActivity splashScreenActivity); //does NOT support base class injection! Concrete classes only!
}

然后

public class SplashScreenActivity extends AppCompatActivity {

    @Inject SessionKeyExchangerService exchangerService;

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

        Injector.INSTANCE.getAppComponent().inject(this);

        // establish the session id as a singleton object
        // exchangerService = component.provideSessionKeyExchangerService(); //totally not needed

        // test whether I can access the singleton from another class
        exchangerService.sendEncryptedKeyToServer();

此外,您正在使用基于 @Module 的实例创建,因此在

中的构造函数中丢失 @Inject
@Inject
public SessionKeyExchangerService(AESCipherService cipherService) {
    this.cipherService = cipherService;
}

还有

public void sendEncryptedKeyToServer () {

    // the next line is almost certainly part of the problem
    // but I don't know how to fix!!!
    //AppComponent component = DaggerAppComponent.builder().appModule(new AppModule()).build(); //you don't need this here at all

    //AESCipherService cipherService = component.provideCipherService(); //already provided in constructor