Подтвердить что ты не робот

Кинжал 2 синглтона не работает

Используя Dagger 2, я пытаюсь внедрить одноэлементный объект в нескольких местах в одной области. Однако кажется, что мое решение вместо этого создает новый экземпляр каждый раз.

В этом тестовом проекте у меня есть MainActivity, который инициализирует DaggerModule. DaggerModule предоставляет объекты Box и Cat, при этом Box принимает параметр Cat. Я также принимаю участие в Cat in my MainActivity. Наконец, я проверяю ссылки на вложенные переменные Cat (в поле и в MainActivity соответственно), но они не являются одним и тем же экземпляром.

Если я сначала вызову функцию enableCat() в моей MainActivity, будет предоставлен тот же самый экземпляр.

MainActivity:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerModule daggerModule = new DaggerModule();
        DaggerComponent daggerComponent = Dagger_DaggerComponent.builder()
                .daggerModule(daggerModule).build();

        // Same Cat instance returned.
        Cat cat1 = daggerComponent.provideCat();
        Cat cat2 = daggerComponent.provideCat();
        Log.d("=== cat1: ", cat1.toString());
        Log.d("=== cat2: ", cat2.toString());

        // Different Cat instance returned. Why?
        Box box = daggerComponent.provideBox();
        Log.d("=== box cat: ", box.getCat().toString());
    }
}

@Module
public class DaggerModule {

    @Provides
    @Singleton
    public Cat provideCat() {
        return new Cat();
    }

    @Provides
    @Singleton
    public Box provideBox() {
        return new Box(provideCat());
    }

}

@Singleton
@Component(modules = { DaggerModule.class })
public interface DaggerComponent {

    Cat provideCat();

    Box provideBox();

}

public class Cat {

    @Inject
    public Cat() {
    }

}

public class Box {

    private Cat mCat;

    @Inject
    public Box(Cat cat) {
        mCat = cat;
    }

    public Cat getCat() {
        return mCat;
    }

}

Спасибо заранее!

Edit: Он работает, если функция allowBox принимает аргумент Cat и использует это для создания поля, вместо того, чтобы вызывать функцию allowCat непосредственно из allowBox.

    // Doesn't work, new Cat instance created.
    @Provides
    @Singleton
    public Box provideBox() {
        return new Box(provideCat());
    }

против

    // Works, same singleton injected.
    @Provides
    @Singleton
    public Box provideBox(Cat cat) {
        return new Box(cat);
    }

Какая разница между вызовом функции enableCat в MainActivity и его выполнением изнутри createBox в DaggerModule? Может быть, компилятор Dagger не обрабатывает DaggerModule так же, как это делает с внешними классами, и аннотации не применяются, если я вызываю там securityCat?

4b9b3361

Ответ 1

Причина, по которой я хотел вызвать securityCat изнутри, была неправильным пониманием в моей части интерфейса Component. Я не понял, что интерфейс Component на самом деле не реализован модулем, поэтому аргументы методов модуля не должны быть объявлены в соответствующих методах компонента. Если бы это было так, это вынудило бы создать экземпляр Cat в вызове метода enableBox MainActivity, который я хотел бы избежать (отсюда вызов обеспеченияCat непосредственно в методе обеспеченияBox модуля). Фактически, объявление аргументов в методах Component даже не позволило компилятору Dagger не скомпилировать.

Но поскольку методы Component не принимают аргументы, решение было просто вводить экземпляры в качестве аргументов в методах модуля, где это необходимо (вместо того, чтобы вызывать соответствующие методы предоставления из самого модуля), и только для вызова Компонентные безпараметрические методы из MainActivity следующим образом:

MainActivity:

Cat cat = daggerComponent.provideCat();
Box box = daggerComponent.provideBox();

компонент:

Cat provideCat();
Box provideBox(); <- no arguments

Модуль:

@Module
public class DaggerModule {

    @Provides
    @Singleton
    public Cat provideCat() {
        return new Cat();
    }

    @Provides
    @Singleton
    public Box provideBox(Cat cat) { <- arguments
        return new Box(cat);
    }

}

Синтаксические экземпляры CatAndivity и Box теперь являются одинаковыми, и мне не нужно было объявлять их из MainActivity, но Кинжал обрабатывал все это. Успех! Все еще не уверены, почему методы по-разному работают при вызове из внешних классов, чем из самого модуля.