Android使用依赖注入简单的自定义类 [英] Android use dependency injection for simple custom class
问题描述
在网上搜索了解此功能后,大多数主题或帖子都使用依赖注入 Retrofit
或其他Android有用的库,但我有一些我想要的自定义类使用它与DI,我不能这样做,例如我有简单的自定义类使用 SharePreference
,我正在使用它作为一个单例类
after search on web for learning about this feature most topics or post was using dependency injection for Retrofit
or other android useful libraries, but i have some custom class which i want to use that with DI and i can't done it, for example i have simple custom class for using SharePreference
and i'm using with that as an Singleton class
在我的代码中我无法将正确的Dagger分配给 SpApplication
类上的组件,以便在活动或片段上使用它
in my code i can't assign correct Dagger to component on SpApplication
class to use that on activities or fragments
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:
now i'm trying to use DI for that:
AppModules类:
AppModules class:
@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
class:
@Component(modules = AppModules.class)
public interface ApplicationComponent {
void inject(ActivityMain activity);
}
SpApplication
class:
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
class:
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
。然后只需将相关部分复制到活动
。
I guess you are trying to inject into ActivityMain
, but since you did not provide its source, let me show you how you could inject into SpApplication
. Then just copy the relevant parts into your Activity
.
我认为您需要更改的内容很少。
Few things I think you need to change.
模块:
您的 AppModules
class通常没问题,但我建议你改变你使用 Context
的方式 - 不要将它用作字段,而是将其作为任何其他服务注入。它看起来像这样:
Your AppModules
class is generally OK, but I just suggest you to change the way you make use of Context
- don't use it as a field, but inject it as any other service. It looks like this:
@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
应如下所示:
Taking into account these two points, ApplicationComponent
should look like this:
@Singleton // injects @Singleton scoped services
@Component(modules = AppModules.class)
public interface ApplicationComponent {
void inject(SpApplication application); // SpApplication is DI client (injection target)
}
客户:
我在 SpApplication
类中更改了一些内容:
I'd change few things in your SpApplication
class:
- 实例化
ApplicationComponent
的方式不正确 - 这不是一个bug ,但你真的不需要
get(上下文)
和getInstance()
方法
- The way you instantiate
ApplicationComponent
is incorrect - This is not a bug, but you don't really need
get(Context)
andgetInstance()
methods
此外,由于我将展示如何注入 SpApplication
,我将添加注入逻辑为好(你应该复制给你的实际客户)。
In addition, since I'm showing how you inject into SpApplication
, I will add the injection logic as well (which you should copy to your actual clients).
所以, SpApplication
(这是DI客户端)应该看起来类似于:
So, SpApplication
(which is DI client) should look similar to this:
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;
}
}
如果您执行上述更改,我倾向于相信你会没事的。
If you perform the above changes, I tend to believe that you'll be all right.
BTW,我最近完成了博客文章。如果你要认真对待依赖注入,你可能想检查它。
BTW, I recently completed a blog post about Dagger 2 scopes. You might want to check it if you are going to be serious about dependency injection.
这篇关于Android使用依赖注入简单的自定义类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!