I am trying to store my user Object as a singleton with Dagger 2.
@Provides
@Named("me")
@Singleton
User provideUser(PrefsUtil prefsUtil, UserDao userDao) {
int id = prefsUtil.getFromPrefs("me", 0);
if (id == 0){
return new User();
}
try {
return userDao.queryForId(id);
} catch (SQLException e) {
return new User();
}
}
It works fine and injects my classes with User object.
However, after logging in and fetching the user from server and storing it in the place the above method queries it from, it will not take effect because it is a singleton. It will provide me with the null user object. In order for it to take effect you have to quit application and reopen it...
The question is how to update/reinitialize the user object annotated with @Name("me") after the actual data is changed so it injects my other classes with the current user object?
Creating Singletons We create a class called NetModule. java and annotate it with @Module to signal to Dagger to search within the available methods for possible instance providers. The methods that will actually expose available return types should also be annotated with the @Provides annotation.
Dagger 2 walks through the dependency graph and generates code that is both easy to understand and trace, while also saving you from writing a large amount of boilerplate code you would normally need to write by hand to obtain references and pass them to other objects as dependencies.
Dagger 2 is a compile-time android dependency injection framework that uses Java Specification Request 330 and Annotations. Some of the basic annotations that are used in dagger 2 are: @Module This annotation is used over the class which is used to construct objects and provide the dependencies.
I'm not going to answer your direct question, but give you an advice how to properly implement the functionality that you need.
You are basically trying to implement some kind of UserManager
functionality. But instead of encapsulating this logic in a dedicated class, you attempt to delegate the user management responsibilities to DI framework.
This is an abuse of DI framework and very sloppy path to go.
What you need is just this:
@Provides
@Singleton
UserManager provideUserManager(PrefsUtil prefsUtil, UserDao userDao) {
return new UserManager(prefUtils, userDao);
}
And expose the required funcitonality in UserManager
:
public class UserManager {
private final PrefsUtil mPrefsUtil;
private final UserDao mUserDao;
public UserManager(PrefsUtil prefsUtil, UserDao userDao) {
mPrefsUtil = prefsUtil;
mUserDao = userDao;
}
public User getCurrentUser() {
int id = mPrefsUtil.getFromPrefs("me", 0);
if (id == 0){
return new User();
}
try {
return mUserDao.queryForId(id);
} catch (SQLException e) {
return new User();
}
}
}
You can see this and this answers in order to get some additional context about DI framework abuse.
You might also want to read this post: Dependency Injection in Android.
Then it no longer may be annotated with Singleton
. You have to create your custom Scope.
Then you take responsibility for the object annotated with your custom scope. As soon as your User
has been updated you are getting rid of the previous component that provided User
object, i.e. nulling it out. Then you are creating a new component and the next time you ask the component to fetch you the User
it will create a new one.
Be aware, that any other provider method in the module, that was annotated with your custom scope, will also return newly created object.
Here's a blog post describing how to do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With