Android使用dependency injection简单的自定义类

在网上搜索了解这个function后,大多数主题或post都使用dependency injectionRetrofit或其他Android有用的库,但我有一些自定义类,我想用DI而我无法完成它,例如我有一个简单的自定义类用于使用SharePreference ,我正在使用它作为Singleton类

在我的代码中,我无法将正确的Dagger分配给SpApplication类上的组件,以便在活动或片段上使用它

 public class SP { private SharedPreferences preferences; private Context context; public SP(Context context) { this.context = context; } private SharedPreferences getPrefs() { return preferences = PreferenceManager.getDefaultSharedPreferences(context); } public String getString(SharedPrefsTypes propertyName) { return getPrefs().getString(propertyName.toString(), ""); } public int getInt(SharedPrefsTypes propertyName) { return getPrefs().getInt(propertyName.toString(), 0); } ... public enum SharedPrefsTypes { Login } } 

现在我正在尝试使用DI:

AppModules类:

 @Module public class AppModules { private Context context; public AppModules(Context context) { this.context = context; } @Provides @Singleton SP provideSharePreferences() { SP sharePreference = new SP(context); return sharePreference; } } 

ApplicationComponent类:

 @Component(modules = AppModules.class) public interface ApplicationComponent { void inject(ActivityMain activity); } 

SpApplication类:

 public class SpApplication extends Application { private static SpApplication self; private ApplicationComponent component; @Override public void onCreate() { super.onCreate(); self = this; component = DaggerApplicationComponent.builder().build(); } public static SpApplication get(Context context) { return (SpApplication) context.getApplicationContext(); } public static SpApplication getInstance() { return self; } public ApplicationComponent getComponent() { return component; } } 

和我的ActivityMain类:

 public class ActivityMain extends AppCompatActivity { @Inject SP sharePreference; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((SpApplication) getApplication()).getComponent().inject(this); sharePreference.setInt(SP.SharedPrefsTypes.Login, 0); } } 

我收到此错误:

 android.app.Application cannot be cast to com.pishguy.yendir.SpApplication 

提前致谢

我猜你试图注入ActivityMain ,但由于你没有提供它的来源,让我告诉你如何注入SpApplication 。 然后只需将相关部分复制到您的Activity

我觉得你需要改变的事情很少。

模块:

您的AppModules类通常没问题,但我建议您更改使用Context – 不要将其用作字段,而是将其作为任何其他服务注入。 它看起来像这样:

 @Module public class AppModules { private Context context; public AppModules(Context context) { this.context = context; } @Provides // this can be non-scoped because anyway the same instance is always returned Context provideContext() { return this.context; } @Provides @Singleton SP provideSharePreferences(Context context) { return new SP(context); // use method-local Context } } 

零件:

  1. 如果组件注入作用域服务(@Singleton是作用域),则组件本身必须是作用域
  2. 如果要注入SpApplication类,则将其声明为组件中的注入客户端

考虑到这两点, ApplicationComponent应如下所示:

 @Singleton // injects @Singleton scoped services @Component(modules = AppModules.class) public interface ApplicationComponent { void inject(SpApplication application); // SpApplication is DI client (injection target) } 

客户:

我在SpApplication类中改变了一些东西:

  1. 实例化ApplicationComponent方式不正确
  2. 这不是一个bug,但你真的不需要get(Context)getInstance()方法

另外,由于我将展示如何注入SpApplication ,我还将添加注入逻辑(您应该将其复制到实际客户端)。

因此, SpApplication (它是DI客户端)看起来应该类似于:

 public class SpApplication extends Application { @Inject SP sp; // the dependency that should be injected private ApplicationComponent component; @Override public void onCreate() { super.onCreate(); getComponent().inject(this); // this is when the actual injection takes place } public ApplicationComponent getComponent() { if (component == null) { // this is the way Dagger components should be instantiated component = DaggerApplicationComponent.builder() .appModules(new AppModules(this)) .build(); } return component; } } 

如果你执行上述更改,我倾向于相信你会没事的。

顺便说一句,我最近完成了一篇关于Dagger 2范围的博客文章 。 如果您要认真考虑dependency injection,您可能需要检查它。