Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 385
Saeed Entezari Avatar asked Feb 07 '17 14:02

Saeed Entezari


People also ask

How do you make a dagger Singleton?

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.

Why use Dagger 2 Android?

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.

What is Dagger2?

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.


2 Answers

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.

like image 160
Vasiliy Avatar answered Oct 21 '22 19:10

Vasiliy


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.

like image 3
azizbekian Avatar answered Oct 21 '22 19:10

azizbekian