2014-07-09 12 views
8

Ich möchte Abhängigkeitsinjektion durch Dagger zu einem Projekt einführen. Der folgende Code dient als Beispiel zur Beschreibung des Problems der Injektion in statische Klassen.Wie injizieren in statische Klassen mit Dolch?

Die statische Methode setupTextView() wird aus mehreren Klassen genannt:

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); 
      } 
     }); 
    } 
} 

Hier ein Beispiel dafür ist, wie die Hilfsmethode verwendet wird:

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

Die in der Hilfsmethode verwendet Verfolgung durch die zur Verfügung gestellt wird Anwendungsklasse:

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; 
    } 

} 

Jetzt möchte ich die tr injizieren acking über Dolch. Wenn ich den Code Refactoring bemerkte ich, dass ich brauchen würde das Tracking-Objekt von meiner Aktivität oder Fragmente zu dem statischen Helfer passieren, da es nicht direkt in die statische Klasse injizieren:

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

Das fühlt sich nicht wie ein gutes Design Muster - seit ich das TrackPoint und das Tracking Objekt passiere. Wie würdest du das verbessern?

+7

NsaTracking? -) – ligi

Antwort

12

In Ihrem TextViewHelper erstellen Sie ein statisches Feld mit dem Tracker.

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); 
      } 
     }); 
    } 
} 

Hier ist, wie das Modul zu konfigurieren:

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

und die wichtigsten, Call injectStatics auf Ihrem Diagramm.

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

Edit:

Wie Sie Dagger in der Dokumentation festgestellt, heißt es, dass statische Injektionen „sollten sparsam verwendet werden, da statische Abhängigkeiten schwer zu testen und Wiederverwendung“ Es ist alles wahr, aber weil Sie gefragt haben, wie man Objekt in die Utility-Klasse injiziert, ist dies die beste Lösung.

Aber wenn Sie Ihren Code wollen mehr überprüfbar sein, erstellen Sie ein Modul wie unten:

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

     @Provides 
     Tracking provideTracker() { 
      ... 
     } 

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

Jetzt können Sie static von TextViewHelper Methoden entfernt werden, da diese Utility-Klasse wird mit Dolch injiziert werden.

public class TextViewHelper { 

    private final Tracking mTracker; 

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

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

So sollte es gemacht werden, wenn Sie guten Praktiken folgen möchten. Beide Lösungen funktionieren, also liegt es an Ihnen, eine auszuwählen.

+1

In Bezug auf ** statische Injektion ** die [Dagger Dokumentation] (http://square.github.io/dagger/#using) besagt, dass * "Diese Funktion sollte sparsam verwendet werden, da statisch Abhängigkeiten sind schwer zu testen und wiederzuverwenden. "*. Glauben Sie, dass das gut getestet werden kann? – JJD

+0

Meiner Meinung nach sollte TextViewHelper keine Klasse mit statischen Methoden sein. Behandeln Sie es als ein weiteres injizierbares Objekt, so dass Sie keine statische Injektion mehr benötigen. Erstellen Sie zwei Methoden in Ihrem Modul, eines, das Tracker bereitstellt, und eines, das TextViewHelper bereitstellt.Erstellen Sie in einer Klasse, die TextViewHelper benötigt, ein Feld mit @Inject. Auf diese Weise wird Ihr Code super testbar sein und Sie werden keine statische Injektion benötigen. – tomrozb