0

I have an activity where I get the uid of a user from Firebase authentication:

public class MainActivity extends DaggerAppCompatActivity {
     @Inject UserViewModel userViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
        userViewModel.setUid(uid);
    }
}

I'm using this uid in my view model class:

public class UserViewModel extends ViewModel {
    private CollectionReference usersRef;

    @Inject
    UsersViewModel(CollectionReference usersRef) {
        this.usersRef = usersRef;
    }

    void setUid(String uid) {
        DocumentReference uidRef = usersRef.document(uid);
        //Use uidRef
    }
}

And this my app module class:

class AppModule {
    @Singleton
    @Provides
    static FirebaseFirestore provideFirebaseFirestoreInstance() {
        return FirebaseFirestore.getInstance();
    }

    @Singleton
    @Provides
    static CollectionReference provideUsersCollectionRef(FirebaseFirestore db) {
        return db.collection("users");
    }

    @Singleton
    @Provides
    static DocumentReference provideUidDocumentRef(CollectionReference usersRef) {
        return usersRef.document(uid); //How to add the uid here
    }
}

The question is, how can I add the uid in the app module class, so I can inject the DocumentReference directly in my view model class like this:

public class UserViewModel extends ViewModel {
    private DocumentReference uidRef;

    @Inject
    UserViewModel(DocumentReference uidRef) {
        this.uidRef= uidRef;
        //Use uidRef
    }
}
Gustavo Pagani
  • 6,583
  • 5
  • 40
  • 71
Jorn
  • 252
  • 1
  • 15
  • Possible duplicate of [Can I use some kind of assisted Inject with Dagger?](https://stackoverflow.com/questions/29175014/can-i-use-some-kind-of-assisted-inject-with-dagger) – denvercoder9 Sep 18 '19 at 04:33

1 Answers1

1

You have the correct mindset in trying to inject dependencies but unfortunately, not all dependencies can be provided via constructor injection, some of them need some information that is only known at runtime.

Look at your code, UserViewModel is injected in MainActivity, some of its dependencies were provided via constructor injection but you have to provide its uid dependency via a setter injection in the line userViewModel.setUid(uid); once the uid is retrieved at runtime.

Your code seem fine in retrieving the DocumentReference from the list once the uid is known. Maybe change your code in MainActivity to retrieve the DocumentReference and provide it via setter to UserViewModel?

    String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
    userViewModel.setDocumentReference(db.collection("users").document(uid));

If you really want to inject the DocumentReference directly in your view model class like you described, you can add the uid as a constructor parameter to your AppModule.

But assuming that your AppModule is used by your AppComponent which is created in your Application class, you won't have the uid in the Application class to create the AppModule.

So you will have to create another component for your UserViewModel class, something like UserComponent. And create a UserModule which receives the uid as parameter in the constructor.

Then in your MainActivity, once you retrieve the uid, you create the UserComponent:

    UserComponent userComponent = DaggerUserComponent.builder().userModule(new UserModule(uid)).build();
    userViewModel.setUserComponent(userComponent);

and this is how your UserViewModel will look like:

public class UserViewModel extends ViewModel {
    @Inject    
    private DocumentReference uidRef;


    public void setUserComponent(UserComponent userComponent) {
        userComponent.inject(this);
    }
}
Gustavo Pagani
  • 6,583
  • 5
  • 40
  • 71
  • Thanks for your answer Gustavo. So you say that I can then use the `uidRef` in the `UserViewModel` class since it is injected trough `userComponent.inject(this);`? – Jorn Sep 12 '19 at 16:03
  • yes, DocumentReference will be injected when calling userComponent.inject, given UserModule has a provider method for DocumentReference – Gustavo Pagani Sep 12 '19 at 16:12
  • @Jorn can you give a complete solution for this? – meetme Jan 19 '21 at 11:13