I have this simple module SharePreferencesModule.java :
@Module(includes = ApplicationModule.class)
public class SharedPreferencesModule {
@Provides
SharedPreferences sharedPreferences(MyApp app) {
return app.getSharedPreferences("...", Context.MODE_PRIVATE);
}
@Provides
@Named("firstname")
static String getFirstname(SharedPreferences preferences) {
return preferences.getString("firstname", "");
}
}
With this component SharedPreferencesComponent.java :
@Component(modules = SharedPreferencesModule.class)
public interface SharedPreferencesComponent {
void inject(MyFragment myClass);
}
And this class, which is using the module :
public MyFragment extends Fragment {
@Inject
@Name("firstname")
String firstname;
@Override
public void onAttach(Context context) {
// Not posting "Injector" code in the snippet because it is irrelevant
Injector.getSharedPreferencesComponent().inject(this);
}
}
When MyFragment is created I successfully inject the firstname, but if edit the shared prefs, I am still referencing the old value of firstname. Which is normal because Dagger is providing the firstname only when MyFragment is attached.
How can I stay up to date with the shared prefs ?
Should I re-inject MyFragment everytime the shared prefs are updated ? Seems messy to me. Or can I somehow force Dagger to fetch this data for me ?
Should I re-inject MyFragment everytime the shared prefs are updated ?
You should only inject once, in the same way that you don't call the constructor multiple times.
There might be some exceptions where it would indeed be necessary (or preferrable) to inject again, but all of those injections should happen before you start using your objects. Injecting multiple times leads to an inconsistent state where it is unclear which object references which version of your injected objects.
This might work in some cases, but will lead to difficult bugs in others, and either way you will have a hard time to set it up, making sure to update everything. You'd be better off just destroying and recreating the whole fragment everytime something changes.
Injecting an object should be the initial setup that gets done once and after that the class should be ready to use.
If something keeps changing then Dagger is not the best fit to provide it. Your name would possibly be better put in some NameSettings
class
class NameSettings {
private SharedPreferences prefs;
@Inject NameSettings(SharedPreferences prefs) {
this.prefs = prefs;
}
String getName() { return /* load from prefs */ }
void setName(String name) { /* save to prefs */ }
}
Instead of direcyly injecting a name you could now inject NameSettings
and call get / set to update your name. This way you can always read and write the latest value without the need to deal with SharedPreferences directly.
Now your NameSettings
would not change and there would be no need to re-inject it either.
You could even go ahead and return an Observable
(e.g. RxJava, or some custom implementation of an observable pattern) where you can then listen for changes and update your UI dynamically whenever it changes.