我想通过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);
这不是一个好的设计模式 - 因为我传递了TrackPoint
和Tracking
对象。你会如何改善这个?
答案 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) {
...
}
}
如果您想遵循良好做法,应该如何做。这两种解决方案都可以使用,因此您可以选择一种解决方案。