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 } }
零件:
- 如果组件注入作用域服务(@Singleton是作用域),则组件本身必须是作用域
- 如果要注入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
类中改变了一些东西:
- 实例化
ApplicationComponent
方式不正确 - 这不是一个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,您可能需要检查它。