2016-12-11 4 views
6

Чтобы изучить Dagger 2, я решил переписать свое приложение, но я застрял в поиске правильного решения для следующей проблемы.Кинжал 2: как изменить предоставленные зависимости во время выполнения

Для целей данного примера давайте предположим, что у нас есть интерфейс, который называется Mode:

public interface Mode { 
    Object1 obj1(); 

    //some other methods providing objects for app 
} 

и две реализации: NormalMode и DemoMode.

Режим хранится в одноэлементном режиме, поэтому он может быть доступен из любого места приложения.

public enum ModeManager { 
    INSTANCE,; 

    private Mode mode; 

    public Mode mode() { 
    if (mode == null) 
     mode = new NormalMode(); 
    return mode; 
    } 

    public void mode(Mode mode) { //to switch modules at runtime 
    this.mode = mode; 
    } 
} 

NormalMode переключается на DemoMode во время выполнения (скажем, когда пользователь clickcs на фоне пару раз)

public void backgroundClicked5Times(){ 
    ModeManager.INSTANCE.mode(new DemoMode()); 
    //from now on every object that uses Mode will get Demo implementations, great! 
} 

Так первый я избавилась от одноточечного и определенного режима, которые Кинжалы 2:

@Module 
public class NormalModeModule { 
    @Provides 
    public Object1 provideObject1() { 
    return new NormalObject1(); 
    } 
} 

@Module 
public class DemoModeModule { 
    @Provides 
    public Object1 provideObject1() { 
    return new DemoObject1(); 
    } 
} 

Теперь в способе backgroundClicked5Times в вместо того, чтобы иметь дело с singleton, я хотел бы заменить NormalModeModule на DemoModeModule в DAG, чтобы другие классы, которые нуждались в Object1, с этого момента получили бы реализацию DemoObject1.

Как я могу это сделать в кинжале?

Заранее спасибо.

+0

Возможного дубликат [модули Swappable с кинжалом 2] (https://stackoverflow.com/questions/35658488/swappable-modules-with-dagger-2) – tir38

ответ

1

Экспериментировав с кинжалом какое-то время, я придумал решение, которое, кажется, хорошо работает в моем случае использования.

  1. Определить класс, который будет содержать информацию о состоянии о режиме

    public class Conf { 
        public Mode mode; 
    
        public Conf(Mode mode) { 
        this.mode = mode; 
        } 
    
        public enum Mode { 
        NORMAL, DEMO 
        } 
    } 
    
  2. Обеспечить одноплодный экземпляр Conf в модуле

    @Module 
    public class ConfModule { 
        @Provides 
        @Singleton 
        Conf provideConf() { 
        return new Conf(Conf.Mode.NORMAL); 
        } 
    } 
    
  3. Добавить модуль AppComponent

    @Singleton 
    @Component(modules = {AppModule.class, ConfModule.class}) 
    public interface AppComponent { 
        //... 
    } 
    
  4. Определить модули, которые обеспечивают различные объекты, основанные на режиме

    @Module 
    public class Object1Module { 
    
        @Provides 
        Object1 provideObject1(Conf conf) { 
        if (conf.mode == Conf.Mode.NORMAL) 
         return new NormalObject1(); 
        else 
         return new DemoObject1(); 
        } 
    } 
    
  5. Для переключения режима во время выполнения просто впрыснуть Conf объект и изменить его:

    public class MyActivity extends Activity { 
        @Inject Conf conf; 
    
        //... 
    
        public void backgroundClicked5Times(){ 
         conf.mode = Conf.Mode.DEMO; 
    
         //if you have dagger objects in this class that depend on Mode 
         //execute inject() once more to refresh them 
        } 
    } 
    
+0

Кажется, это достойный способ сделать это, но это не будет работать, если предоставленная зависимость (которая должна быть заменена d во время выполнения) является одноэлементным, не так ли? –

+1

Да, если бы вы аннотировали 'обеспечиватьObject1'' @ Singleton', это не сработало бы, но, с другой стороны, это противоречит идее в этом случае использования. Если вы хотите заменить объекты во время выполнения, вы не можете пометить такой метод с помощью '@ Singleton'. С другой стороны, вы можете сделать одиночные одиночные слова «NormalObject1» и «DemoObject1», поэтому метод, предоставляющий зависимости, не будет создавать более двух экземпляров. – Marcin

+0

Последнее предложение - это информация, в которой я нуждался. Отличное решение, thx :) –

Смежные вопросы