2014-12-02 14 views
23

Natknąłem się na bardzo interesującą bibliotekę Dependency Injection pod nazwą . Przy użyciu można łatwo wprowadzać Widoki do działań lub fragmentów.Widok z wtryskiem noża Buttermnife

class ExampleActivity extends Activity { 
    @InjectView(R.id.title) TextView title; 
    @InjectView(R.id.subtitle) TextView subtitle; 
    @InjectView(R.id.footer) TextView footer; 

    @Override public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.simple_activity); 
    ButterKnife.inject(this); 
    // TODO Use "injected" views... 
    } 
} 

Jednak w przypadku korzystania z Dependency Injection opinie te muszą być public tak, że można go wstrzyknąć Butterknife (używając private wyników pól w wyjątku fields must not be private or static).

W moim poprzednim projekcie zawsze tworzyłem wszystkie pola członkowskie (łącznie z widokami) private, ponieważ uważałem, że jest to najlepsza praktyka (ukrywanie informacji itp.) Teraz zastanawiam się, czy istnieje powód, dla którego nie należy robić wszystkich widoki public? W tym przypadku nie mogę użyć , ale chcę go użyć, ponieważ znacznie upraszcza kod.

+0

Czy Guice nie robi tak samo lepiej, ale bez zepsucia kodu? –

+0

Dlaczego uważasz, że to psuje kod? – Moonlit

+0

@G_V: Może, ale Google mówi, żeby go nie używać. Zobacz http://stackoverflow.com/questions/24194283/does-avoid-dependency-injection-frameworks-in-the-android-memory-guide-apply-t i http://stackoverflow.com/questions/5067681/guice - wydajność na Androida. –

Odpowiedz

44

Po pierwsze, Masło Knife nie jest biblioteką wtrysku zależności. Można go traktować jako bibliotekę redukcyjną, ponieważ zastępuje ona findViewById i różne wywołania setXxxListener.

Powód, dla którego Butter Knife wymaga poglądów, które nie są prywatne, faktycznie generuje kod, który ustawia pola. Kod, który generuje, znajduje się w tym samym pakiecie co klasa, dlatego pole musi być pakietem prywatnym, chronionym lub publicznym. Jeśli pole jest prywatne, wygenerowany kod nie może się skompilować, ponieważ nie może uzyskać dostępu do pola prywatnego.

Wygenerowany kod wygląda mniej więcej tak:

public static void inject(ExampleActivity target, ExampleActivity source) { 
    target.title = (TextView) source.findViewById(R.id.title); 
    target.subtitle = (TextView) source.findViewById(R.id.subtitle); 
    target.footer = (TextView) source.findViewById(R.id.footer); 
} 

Po wywołaniu ButterKnife.inject(this) wygląda tę klasę generowania i wywołuje metodę inject z instancji ExampleActivity zarówno jako cel dla pól i źródła Połączenia findViewById.

+1

Dziękuję za wyjaśnienia. Czy, według Pana, deklarowanie pól, paczki - prywatne, czy nawet publiczne, nie jest uważane za złą praktykę? Zastanawiam się tylko, ponieważ ZAWSZE zadeklarowałem, że moje pola są prywatne i dla mnie to trochę źle. Ale jednocześnie myślę, że to nie ma wielkiej różnicy ... prawda? – Moonlit

+8

Myślę, że pakiet prywatny jest wystarczająco ograniczony pod względem zakresu, że nie jest to wielka sprawa. Jeśli nie możesz zaufać innym klasom w pakiecie, to masz inne problemy :) Dodatkowo pakiet-private jest również używany do ujawniania rzeczy do testowania klas, więc jest dość powszechny. Nie robiłbym tego jednak publicznie, nadal chcesz ukryć te pola jako szczegół implementacji. –

+2

To sprawia, że ​​kodowanie jest trudniejsze do odczytania i utrzymania, poprzez ujawnienie rzeczy, których nie należy dotykać. Zawsze powinieneś dążyć do napisania kodu, który ktoś mógłby przeczytać bez spędzania wielu godzin, aby dowiedzieć się, co się dzieje. Jest to bezużyteczne w przypadku zmiennych, do których nie należy uzyskiwać dostępu poza swoim programem pobierającym lub ustawiającym, w którym znajdują się kontrole i inne elementy sterujące. –