简体   繁体   中英

Dagger 2 reinit singleton

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?

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, ie 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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM