2015-08-25 3 views
4

Я работал над пониманием и настройкой кинжала для обработки инъекций зависимостей для моего проекта Android. Цель моего единственного (не предназначенного для каламбура) заключается в создании одноэлементных объектов, к которым я могу получить доступ в моем приложении. Я успешно создал объекты в начальной активности. Где я застрял в доступе к этим объектам из других классов. Вот моя установка до сих пор:Кинжал - доступ к объекту Singleton из другого класса

Initial App активность

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(); 
    } 

компонентов класса

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

    SessionKeyExchangerService provideSessionKeyExchangerService(); 

    AESCipherService provideCipherService(); 
} 

модуль класса

@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; 
    } 
} 

SessionKeyExchanger Класс

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))); 
    } 

Вот некоторые пример вывода:

Идентификатор сеанса: 217186720
одноэлементный проверка: 790090968

Очевидно, что я не получаю доступ к одному и тому же объекту. Я понимаю, что, по крайней мере, часть части проблемы связана с тем, что я называю оператором new в AESCipherService, когда пытаюсь получить ссылку на класс AppComponent, но я не знаю, как получить эту ссылку другой путь.

Как исправить это? Благодаря!

ответ

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

Nononononono. Это не будет Синглтон. Скоординированные поставщики работают только на один компонент, а это означает, что вы должны использовать один компонент в своем приложении для облачных модулей @Singleton, которые фактически используют одного и того же провайдера. В этом случае вы будете создавать новый компонент каждый раз, когда ваша деятельность будет создана.

Вам нужно создать их, как это:

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 
Смежные вопросы