2015-02-27 7 views
7

Próbuję po raz pierwszy sztylet, a po skonfigurowaniu modułu otrzymuję błąd, którego nie rozumiem.Sztylet: klasa nie mogła być powiązana z kluczem

Mój kod to:

public class Parrot { 

    private Language language; 

    @Inject 
    public Parrot(Language language) { 
     this.language = language; 
    } 

    public void sayHello() { 
     System.out.println(language.getSalute()); 
    } 
} 

public interface Language { 
    public String getSalute(); 
} 

public class EnglishLanguage implements Language { 

    @Override 
    public String getSalute() { 
     return "Hello!"; 
    } 
} 

Mój moduł jest

@Module(
     injects = Language.class 
) 
public class PetShopModule { 

    @Provides Parrot provideParrot(Parrot parrot){ 
     return parrot; 
    } 
} 

I w kodzie używam go w ten sposób

EnglishLanguage lang=SystemApp.getSystemLanguage(); 
ObjectGraph objectGraph = ObjectGraph.create(new PetShopModule()); 
objectGraph.inject(myLanguage); 
Parrot parrot = objectGraph.get(Parrot.class); 

Kompilator narzeka:

error: com.example.petshop.Language could not be bound 
with key com.example.petshop.Language required by com.example.petshop.PetShopModule 
for com.example.petshop.PetShopModule 

Co robię źle?

Uwaga: Jest to tylko uproszczony przykład, w prawdziwym kodzie EnglishLanguage to system klasy i nie mogą modyfikować ani tworzyć go, po prostu odniesienie

Odpowiedz

13

Zamiast komentując co masz robić źle, dajmy właściwy przykład i wyjaśnijmy, co się tam dzieje.

Ten fragment jest doskonały, i pozostaje, jak to jest:

public class Parrot { 

    private Language language; 

    @Inject 
    public Parrot(Language language) { 
     this.language = language; 
    } 

    public void sayHello() { 
     System.out.println(language.getSalute()); 
    } 
} 

public interface Language { 
    public String getSalute(); 
} 

public class EnglishLanguage implements Language { 

    @Override 
    public String getSalute() { 
     return "Hello!"; 
    } 
} 

Z @Inject adnotacji na konstruktora Parrot, mówisz sztylet „Ilekroć zażądania wystąpienie Parrot, należy użyć tego konstruktora utworzyć instancję ".

Sztylet widzi, że Parrot potrzebuje instancji interfejsu Language i próbuje znaleźć sposób na jej odzyskanie. Ponieważ jednak interfejs to Language, Dagger musi wiedzieć, który typ betonu należy użyć.

Ponieważ nie można edytować klasę EnglishLanguage, musisz napisać @Provider metodę nim:

@Module 
public class PetshopModule { 

    @Provides 
    Language provideLanguage() { 
    return SystemApp.getSystemLanguage(); 
    } 
} 

Teraz powinieneś być w stanie uzyskać instancję Parrot ze swojego ObjectGraph, jak to :

ObjectGraph graph = ObjectGraph.create(new PetshopModule()); 
Parrot parrot = graph.get(Parrot.class); 

Nie testowałem tego, bit to powinno działać.


Jeśli były stanie zmodyfikować klasę EnglishLanguage, można wykonać następujące czynności. Opisywanie konstruktora EnglishLanguage z @Inject i poprosić o wystąpienie EnglishLanguage w metodzie Language provider:

public class EnglishLanguage implements Language { 

    @Inject 
    public EnglishLanguage() { 
    } 

    @Override 
    public String getSalute() { 
    return "Hello!"; 
    } 
} 

@Module 
public class PetshopModule { 

    @Provides 
    Language provideLanguage(EnglishLanguage language) { 
    return language; 
    } 
} 

W tym przypadku Dagger szuka sposobu dostawcy Language oraz instancję EnglishLanguage wrócić.

Powiązane problemy