使用 Dagger 2 注入 SharedPreference class 时出现问题
Having problem in injecting SharedPreference class using Dagger 2
我是 Dagger 概念的新手,我猜我已经在一定程度上理解了,但在注入 classes 时一直遇到问题。我浏览了很多教程和示例代码,但是当我必须使用一个组件对多个模块进行操作时,我最终遇到了一个错误,而且大多数情况下,共享首选项模块没有被注入。无法理解实际错误或我犯的错误,需要一些帮助。
我的组件class:
@Singleton
@Component(modules = {VehicleModule.class, AppPreference.class})
public interface AppComponent {
// void injectPreference(MainActivity activity);
void inject(MainActivity activity);
Vehicle provideVehicle();
}
我的共同偏好class:
@Module
public class AppPreference {
private SharedPreferences preferences;
private SharedPreferences.Editor edit;
@ApplicationScope
@Provides
@Inject
public SharedPreferences getPreferences() {
return preferences;
}
public AppPreference(Context context) {
// preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences = context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
edit = preferences.edit();
}
@Singleton
@Provides
public String setDataPref(String strKey, String strValue) {
edit.putString(strKey, strValue);
commitPreference();
return strKey;
}
@Singleton
@Provides
public String removeFromPreference(String strKey) {
edit.remove(strKey);
return strKey;
}
public void commitPreference()
{
edit.commit();
}
@Singleton
@Provides
public String getDataPref(String strKey) {
return preferences.getString(strKey, "");
}
@Singleton
@Provides
public boolean clear() {
edit.clear();
commitPreference();
return true;
}
}
我的申请Class:
public class AppInstance extends Application {
AppComponent component;
@Override
public void onCreate() {
super.onCreate();
component = DaggerAppComponent.builder().appPreference(new AppPreference(getApplicationContext())).build();
}
public AppComponent getComponent() {
return component;
}
}
最后我的 Activity:
public class MainActivity extends AppCompatActivity {
// @Inject
// AppPreference preference;
private AppComponent appComponent;
Vehicle vehicle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
appComponent = DaggerAppComponent.builder().vehicleModule(new VehicleModule()).build();
vehicle = appComponent.provideVehicle();
((AppInstance) getApplicationContext()).getComponent().inject(this);
}
}
此代码能够构建 DaggerAppComponent,但是一旦我在 Mainactivity 中注入 AppPreference,它就不再起作用了。
我在注入首选项时做错了什么 class?
需要帮助..
您需要将 SharedPreference class 的实例提供到 Dagger Graph 中,根据您的代码,您可以实现以下目标,
AppModule.java
@Module
class AppModule{
@Provides
@Singleton
public SharedPreference providesSharedPreferences(application:Application){
return new AppPreference(application);
}
}
AppPreferences.java
public class AppPreference {
private SharedPreferences preferences;
private SharedPreferences.Editor edit;
public SharedPreferences getPreferences() {
return preferences;
}
public AppPreference(Context context) {
// preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences = context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
edit = preferences.edit();
}
public String setDataPref(String strKey, String strValue) {
edit.putString(strKey, strValue);
commitPreference();
return strKey;
}
public String removeFromPreference(String strKey) {
edit.remove(strKey);
return strKey;
}
public void commitPreference()
{
edit.commit();
}
public String getDataPref(String strKey) {
return preferences.getString(strKey, "");
}
public boolean clear() {
edit.clear();
commitPreference();
return true;
}
}
AppComponent.java
@Singleton
@Component(modules = {VehicleModule.class, AppModule.class})
public interface AppComponent {
void inject(MainActivity activity);
Vehicle provideVehicle();
}
MainActivity.java
class MainActivity extends Activity{
@Inject
SharedPreference sharedPreference; //this is injected like this
}
在你的情况下,我会让 AppPreference 成为一个单例,并在需要的地方@Inject 它。
首先,您的组件应该如下所示:
@Singleton // Constraints this component to one-per-application or unscoped bindings.
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(MainActivity mainActivity);
//Exposed to sub-graphs
Context context();
AppPreference appPreference();
}
}
那么你的模块应该是这样的:
@Module
public class ApplicationModule {
private final Application application;
public ApplicationModule(Application application) {
this.application = application;
}
private final Application application;
public ApplicationModule(Application application) {
this.application = application;
}
@Provides
@Singleton
Context provideApplicationContext() {
return application;
}
@Provides
@Singleton
AppPreference provideAppPreference() {
return new AppPreference(provideApplicationContext());
}
}
然后在您的应用程序 class 中初始化应用程序组件,同时保留对它的引用以便您以后可以使用它:
public ApplicationComponent getComponent() {
return applicationComponent;
}
private void initializeInjector() {
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
}
像这样在 onCreate() 上注入 Main Activity 后:
MyApplication.get(this).getComponent().inject(this);
您终于可以使用了:
@Inject
AppPreference preference;
您弄错了几个概念和注释。
您可以通过使用 @Inject
注释字段或构造函数来注入对象。对于 Android 活动,您只能使用字段方法。所以你的 MainActivity.class
应该看起来更像这样:
public class MainActivity extends AppCompatActivity {
@Inject
SharedPreference preference;
@Inject
Vehicle vehicle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Inject dependencies into MainActivity
((AppInstance) getApplicationContext()).getComponent().inject(this);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
}
您也不需要在 AppPreferences 模块中使用 @Inject
注释,因为您是 提供 依赖项,而不是 注入 那里。
说到提供,只要要注入 return 类型,就会调用带有 @Provides
注释的方法。如果有多个具有相同 return 类型的提供程序方法,则必须使用 @Named
注释或自定义限定符来区分它们。您的 AppPreferences
模块中有多个 return String
提供程序方法,但是我认为它们没有正确标记为提供程序,它们看起来更像是对 SharedPreferences
对象。清理后你应该留下这个模块:
@Module
public class AppPreference {
private SharedPreferences preferences;
public AppPreference(Context context) {
preferences = context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
}
@ApplicationScope
@Provides
public SharedPreferences getPreferences() {
return preferences;
}
}
并且您必须像对 Vehicle
class:
那样在组件中公开 SharedPreferences
@Singleton
@Component(modules = {VehicleModule.class, AppPreference.class})
public interface AppComponent {
void inject(MainActivity activity);
SharedPreferences sharedPreferences();
Vehicle vehicle();
}
编辑:
如果你想要某种 SharedPreferences
功能的包装器,你可以创建一个自定义的 class (它既不是 Dagger 组件也不是模块),例如MyAppPreferences
:
public class MyAppPreferences {
private SharedPreferences preferences;
public MyAppPreferences(SharedPreferences preferences) {
this.preferences = preferences;
}
// put setDataPref, removeFromPref, etc. in here
}
然后像这样注入:
@Module
public class AppPreferencesModule {
private Context context;
public AppPreferencesModule(Context context) {
this.context = context;
}
// Dagger will inject the SharedPreferences object using the providePreferences() provider
@ApplicationScope
@Provides
public MyAppPreferences provideMyAppPreferences(SharedPreferences preferences) {
return new MyAppPreferences(preferences);
}
@ApplicationScope
@Provides
private SharedPreferences providePreferences() {
return context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
}
}
@Singleton
@Component(modules = {VehicleModule.class, AppPreferencesModule.class})
public interface AppComponent {
void inject(MainActivity activity);
// expose MyAppPreferences instead of SharedPreferences
MyAppPreferences myAppPreferences();
Vehicle vehicle();
}
public class MainActivity extends AppCompatActivity {
// inject MyAppPreferences instead of SharedPreferences
@Inject
MyAppPreferences myAppPreferences;
...
}
我是 Dagger 概念的新手,我猜我已经在一定程度上理解了,但在注入 classes 时一直遇到问题。我浏览了很多教程和示例代码,但是当我必须使用一个组件对多个模块进行操作时,我最终遇到了一个错误,而且大多数情况下,共享首选项模块没有被注入。无法理解实际错误或我犯的错误,需要一些帮助。
我的组件class:
@Singleton
@Component(modules = {VehicleModule.class, AppPreference.class})
public interface AppComponent {
// void injectPreference(MainActivity activity);
void inject(MainActivity activity);
Vehicle provideVehicle();
}
我的共同偏好class:
@Module
public class AppPreference {
private SharedPreferences preferences;
private SharedPreferences.Editor edit;
@ApplicationScope
@Provides
@Inject
public SharedPreferences getPreferences() {
return preferences;
}
public AppPreference(Context context) {
// preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences = context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
edit = preferences.edit();
}
@Singleton
@Provides
public String setDataPref(String strKey, String strValue) {
edit.putString(strKey, strValue);
commitPreference();
return strKey;
}
@Singleton
@Provides
public String removeFromPreference(String strKey) {
edit.remove(strKey);
return strKey;
}
public void commitPreference()
{
edit.commit();
}
@Singleton
@Provides
public String getDataPref(String strKey) {
return preferences.getString(strKey, "");
}
@Singleton
@Provides
public boolean clear() {
edit.clear();
commitPreference();
return true;
}
}
我的申请Class:
public class AppInstance extends Application {
AppComponent component;
@Override
public void onCreate() {
super.onCreate();
component = DaggerAppComponent.builder().appPreference(new AppPreference(getApplicationContext())).build();
}
public AppComponent getComponent() {
return component;
}
}
最后我的 Activity:
public class MainActivity extends AppCompatActivity {
// @Inject
// AppPreference preference;
private AppComponent appComponent;
Vehicle vehicle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
appComponent = DaggerAppComponent.builder().vehicleModule(new VehicleModule()).build();
vehicle = appComponent.provideVehicle();
((AppInstance) getApplicationContext()).getComponent().inject(this);
}
}
此代码能够构建 DaggerAppComponent,但是一旦我在 Mainactivity 中注入 AppPreference,它就不再起作用了。
我在注入首选项时做错了什么 class? 需要帮助..
您需要将 SharedPreference class 的实例提供到 Dagger Graph 中,根据您的代码,您可以实现以下目标,
AppModule.java
@Module
class AppModule{
@Provides
@Singleton
public SharedPreference providesSharedPreferences(application:Application){
return new AppPreference(application);
}
}
AppPreferences.java
public class AppPreference {
private SharedPreferences preferences;
private SharedPreferences.Editor edit;
public SharedPreferences getPreferences() {
return preferences;
}
public AppPreference(Context context) {
// preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences = context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
edit = preferences.edit();
}
public String setDataPref(String strKey, String strValue) {
edit.putString(strKey, strValue);
commitPreference();
return strKey;
}
public String removeFromPreference(String strKey) {
edit.remove(strKey);
return strKey;
}
public void commitPreference()
{
edit.commit();
}
public String getDataPref(String strKey) {
return preferences.getString(strKey, "");
}
public boolean clear() {
edit.clear();
commitPreference();
return true;
}
}
AppComponent.java
@Singleton
@Component(modules = {VehicleModule.class, AppModule.class})
public interface AppComponent {
void inject(MainActivity activity);
Vehicle provideVehicle();
}
MainActivity.java
class MainActivity extends Activity{
@Inject
SharedPreference sharedPreference; //this is injected like this
}
在你的情况下,我会让 AppPreference 成为一个单例,并在需要的地方@Inject 它。
首先,您的组件应该如下所示:
@Singleton // Constraints this component to one-per-application or unscoped bindings.
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(MainActivity mainActivity);
//Exposed to sub-graphs
Context context();
AppPreference appPreference();
}
}
那么你的模块应该是这样的:
@Module
public class ApplicationModule {
private final Application application;
public ApplicationModule(Application application) {
this.application = application;
}
private final Application application;
public ApplicationModule(Application application) {
this.application = application;
}
@Provides
@Singleton
Context provideApplicationContext() {
return application;
}
@Provides
@Singleton
AppPreference provideAppPreference() {
return new AppPreference(provideApplicationContext());
}
}
然后在您的应用程序 class 中初始化应用程序组件,同时保留对它的引用以便您以后可以使用它:
public ApplicationComponent getComponent() {
return applicationComponent;
}
private void initializeInjector() {
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
}
像这样在 onCreate() 上注入 Main Activity 后:
MyApplication.get(this).getComponent().inject(this);
您终于可以使用了:
@Inject
AppPreference preference;
您弄错了几个概念和注释。
您可以通过使用 @Inject
注释字段或构造函数来注入对象。对于 Android 活动,您只能使用字段方法。所以你的 MainActivity.class
应该看起来更像这样:
public class MainActivity extends AppCompatActivity {
@Inject
SharedPreference preference;
@Inject
Vehicle vehicle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Inject dependencies into MainActivity
((AppInstance) getApplicationContext()).getComponent().inject(this);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
}
您也不需要在 AppPreferences 模块中使用 @Inject
注释,因为您是 提供 依赖项,而不是 注入 那里。
说到提供,只要要注入 return 类型,就会调用带有 @Provides
注释的方法。如果有多个具有相同 return 类型的提供程序方法,则必须使用 @Named
注释或自定义限定符来区分它们。您的 AppPreferences
模块中有多个 return String
提供程序方法,但是我认为它们没有正确标记为提供程序,它们看起来更像是对 SharedPreferences
对象。清理后你应该留下这个模块:
@Module
public class AppPreference {
private SharedPreferences preferences;
public AppPreference(Context context) {
preferences = context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
}
@ApplicationScope
@Provides
public SharedPreferences getPreferences() {
return preferences;
}
}
并且您必须像对 Vehicle
class:
SharedPreferences
@Singleton
@Component(modules = {VehicleModule.class, AppPreference.class})
public interface AppComponent {
void inject(MainActivity activity);
SharedPreferences sharedPreferences();
Vehicle vehicle();
}
编辑:
如果你想要某种 SharedPreferences
功能的包装器,你可以创建一个自定义的 class (它既不是 Dagger 组件也不是模块),例如MyAppPreferences
:
public class MyAppPreferences {
private SharedPreferences preferences;
public MyAppPreferences(SharedPreferences preferences) {
this.preferences = preferences;
}
// put setDataPref, removeFromPref, etc. in here
}
然后像这样注入:
@Module
public class AppPreferencesModule {
private Context context;
public AppPreferencesModule(Context context) {
this.context = context;
}
// Dagger will inject the SharedPreferences object using the providePreferences() provider
@ApplicationScope
@Provides
public MyAppPreferences provideMyAppPreferences(SharedPreferences preferences) {
return new MyAppPreferences(preferences);
}
@ApplicationScope
@Provides
private SharedPreferences providePreferences() {
return context.getSharedPreferences(context.getString(R.string.app_name), MODE_PRIVATE);
}
}
@Singleton
@Component(modules = {VehicleModule.class, AppPreferencesModule.class})
public interface AppComponent {
void inject(MainActivity activity);
// expose MyAppPreferences instead of SharedPreferences
MyAppPreferences myAppPreferences();
Vehicle vehicle();
}
public class MainActivity extends AppCompatActivity {
// inject MyAppPreferences instead of SharedPreferences
@Inject
MyAppPreferences myAppPreferences;
...
}