2014-07-09 16 views
8

Chcę wprowadzić zastrzyk zależności za pośrednictwem Dagger do projektu. Poniższy kod służy jako przykład do opisania problemu wtrysku do klas statycznych.Jak wstrzykiwać do klas statycznych za pomocą sztyletu?

Statyczna metoda setupTextView() jest wywoływana z wielu klas:

public abstract class TextViewHelper { 
    public static void setupTextView(TextView textView, 
            Spanned text, 
            TrackingPoint trackingPoint) { 
     textView.setText(text, TextView.BufferType.SPANNABLE); 
     textView.setMovementMethod(LinkMovementMethod.getInstance()); 
     textView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       MyApp.getTracker().track(trackingPoint); 
      } 
     }); 
    } 
} 

Oto jeden z przykładów, jak stosowana jest metoda pomocnika:

TextViewHelper.setupTextView(this, R.id.some_text_view, 
          R.string.some_text, 
          TrackingPoint.SomeTextClick); 

Śledzenie stosowany w metodzie pomocnika jest zapewniana przez klasa aplikacji:

public class MyApp extends Application { 

    private static Tracking mTracking; 

    public void onCreate() { 
     super.onCreate(); 
     mTracking = getTracking(getApplicationContext()); 
    } 

    private Tracking getTracking(Context context) { 
     if (BuildConfig.DEBUG) { 
      return new NoTracking(); 
     } else { 
      return new NsaTracking(context); 
     } 
    } 

    public static Tracking getTracker() { 
     return mTracking; 
    } 

} 

Teraz chcę wstrzyknąć potwierdzenie przez Dagger. Kiedy refactored kod zauważyłem, że muszę przekazać obiekt do śledzenia z mojej działalności lub fragment do statycznej pomocnika, ponieważ nie można bezpośrednio wprowadzić do klasy statycznej:

TextViewHelper.setupTextView(this, R.id.some_text_view, 
          R.string.some_text, 
          TrackingPoint.SomeTextClick, 
          Tracking tracking); 

nie czuć się jak dobry projekt wzór - od momentu przejścia przez obiekt TrackPoint i Tracking. Jak mógłbyś to poprawić?

+7

NsaTracking? -) – ligi

Odpowiedz

12

W swoim TextViewHelper utwórz statyczne pole z trackerem.

public class TextViewHelper { 

    private TextViewHelper(){} 

    @Inject 
    static Tracking sTracker; 

    public static void setupTextView(TextView textView, 
            Spanned text, 
            TrackingPoint trackingPoint) { 
     textView.setText(text, TextView.BufferType.SPANNABLE); 
     textView.setMovementMethod(LinkMovementMethod.getInstance()); 
     textView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       sTracker.track(trackingPoint); 
      } 
     }); 
    } 
} 

Oto jak skonfigurować moduł:

@Module(staticInjections = TextViewHelper.class) 
public class TrackerModule { 
... 
} 

i najważniejsze, injectStatics kupna na wykresie.

mObjectGraph = ObjectGraph.create(new TrackerModule()); 
mObjectGraph.injectStatics(); 

Edit:

Jak można zauważyć, dokumentacja Dagger stwierdza, że ​​zastrzyki statyczne „powinny być stosowane oszczędnie, ponieważ Zależności statyczne są trudne do testowania i ponownego użycia” To wszystko prawda, ale ponieważ zapytano, jak wprowadzić obiekt do klasy użytkowej, jest to najlepsze rozwiązanie.

Ale jeśli chcesz, aby Twój kod będzie bardziej sprawdzalne, należy utworzyć moduł jak poniżej:

@Module(injects = {classes that utilizes TextViewHelper}) 
public class TrackerModule { 

     @Provides 
     Tracking provideTracker() { 
      ... 
     } 

     @Provides 
     @Singleton 
     TextViewHelper provideTextViewHelper(Tracking tracker) { 
      return new TextViewHelper(tracker); 
     } 
} 

Teraz można usunąć static z TextViewHelper metod, ponieważ ta klasa narzędzie będzie wstrzykiwany przy użyciu sztyletu.

public class TextViewHelper { 

    private final Tracking mTracker; 

    public TextViewHelper(Tracking tracker){ 
     mTracker = tracker; 
    } 

    public void setupTextView(TextView textView, 
           Spanned text, 
           TrackingPoint trackingPoint) { 
     ... 
    } 
} 

Tak należy postępować, jeśli chce się stosować dobrych praktyk. Oba rozwiązania będą działać, więc wybór należy do Ciebie.

+1

W odniesieniu do ** statycznego wtrysku ** [Dokumentacja Sztyletu] (http://square.github.io/dagger/#using) stwierdza, że ​​* "Ta funkcja powinna być używana oszczędnie, ponieważ statyczne zależności są trudne do przetestowania i ponownego użycia. "*. Czy uważasz, że można to dobrze przetestować? – JJD

+0

Moim zdaniem TextViewHelper nie powinien być klasą ze statycznymi metodami. Traktuj to jako inny obiekt do wstrzykiwania, więc nie będziesz już potrzebował statycznej iniekcji. Utwórz dwie metody w swoim module, jedna zapewniająca Tracker, a druga zapewniająca TextViewHelper.W klasie, która potrzebuje TextViewHelper po prostu utwórz pole z @Inject. W ten sposób twój kod będzie super testowalny i nie będziesz potrzebował statycznego wtrysku. – tomrozb

Powiązane problemy