如何使用Dagger注入静态类?

时间:2014-07-09 14:52:08

标签: android dependency-injection dagger static-classes

我想通过Dagger向项目引入依赖注入。以下代码用作描述注入静态类的问题的示例。

从多个类调用静态方法setupTextView()

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

以下是如何使用辅助方法的一个示例:

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

辅助方法中使用的跟踪由应用程序类提供:

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

}

现在,我想通过Dagger注入跟踪。当我重构代码时,我注意到我需要将跟踪对象从我的Activity或Fragment传递给静态助手,因为我无法直接注入静态类:

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

这不是一个好的设计模式 - 因为我传递了TrackPointTracking对象。你会如何改善这个?

1 个答案:

答案 0 :(得分:14)

TextViewHelper中使用跟踪器创建静态字段。

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

以下是配置模块的方法:

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

最重要的是,在图表上调用injectStatics。

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

修改

正如您所指出的那样,Dagger的文档指出静态注入"应该谨慎使用,因为静态依赖很难测试和重用。" 这是真的,但是因为你问过如何将对象注入实用程序类,这是最好的解决方案。

但如果您希望您的代码更易于测试,请创建如下所示的模块:

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

      @Provides
      Tracking provideTracker() {
           ...
      }

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

现在您可以从static方法中删除TextViewHelper,因为此实用程序类将使用dagger注入。

public class TextViewHelper {

    private final Tracking mTracker;

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

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

如果您想遵循良好做法,应该如何做。这两种解决方案都可以使用,因此您可以选择一种解决方案。