Jarnojr
Jarnojr

Reputation: 714

@Inject in BaseActivity

I am following coding with mitch's dagger 2 course from youtube.I am confused about something.Here is my classes: AppComponent.class

@Singleton
@Component(
        modules = {
                AndroidSupportInjectionModule.class,
                ActivityBuildersModule.class,
                AppModule.class,
                ViewModelFactoryModule.class,
        }
)
public interface AppComponent extends AndroidInjector<BaseApplication> {
    
    SessionManager sessionManager();

    @Component.Builder
    interface Builder{

        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

}

ActivityBuildersModule

@Module
public abstract class ActivityBuildersModule {

    @ContributesAndroidInjector(
            modules = {AuthViewModelsModule.class,
                    AuthModule.class
            }
    )
    abstract AuthActivity contributeAuthActivity();

    @ContributesAndroidInjector
    abstract MainActivity contributeMainActivity();

}

BaseActivity

public abstract class BaseActivity extends DaggerAppCompatActivity {

    private static final String TAG = "BaseActivity";
    @Inject
    public SessionManager sessionManager;//confused here

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        subscribeObservers();
    }

    private void subscribeObservers() {
        sessionManager.getAuthUser().observe(this, userAuthResource -> {
            if (userAuthResource != null) {
                switch (userAuthResource.status) {
                    case LOADING: {
                        break;
                    }
                    case AUTHENTICATED: {
                        Log.d(TAG, "subsrcibeObservers: LOGIN SUCCESS:" + userAuthResource.data.getEmail());
                        break;
                    }
                    case ERROR: {
                        Toast.makeText(this, userAuthResource.message, Toast.LENGTH_SHORT).show();
                        break;
                    }
                    case NOT_AUTHENTICATED: {
                        navLoginScreen();
                        break;
                    }
                }
            }
        });
    }
    private void navLoginScreen(){
        Intent intent = new Intent(this, AuthActivity.class);
        startActivity(intent);
        finish();
    }

}

MainActivity

public class MainActivity extends BaseActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

SessionManager

@Singleton
public class SessionManager {
    private static final String TAG = "SessionManager";

    private MediatorLiveData<AuthResource<User>> cachedUser = new MediatorLiveData<>();

    @Inject
    public SessionManager() {

    }
    public void authenticaWithId(final LiveData<AuthResource<User>> source) {
        if (cachedUser != null) {
            cachedUser.setValue(AuthResource.loading(null));
            cachedUser.addSource(source, userAuthResource -> {
                cachedUser.setValue(userAuthResource);
                cachedUser.removeSource(source);
            });
        }
    }

    public void logOut(){
        Log.d(TAG, "logOut: logging out...");
        cachedUser.setValue(AuthResource.logout());
    }
    public LiveData<AuthResource<User>> getAuthUser(){
        return cachedUser;
    }
}

BaseApplication

public class BaseApplication extends DaggerApplication {
    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerAppComponent.builder().application(this).build();
    }
}

My problem is @Inject SessionManager sessionManager that statement in the BaseActivity.In the ActivityBuildersModule class, we only annotated MainActivity as a subcomponent, not the BaseActivity.Since the MainActivity is a subcomponent it can access dependencies of the AppComponent.So how we get accessed that SessionManager in the Base Activity or we get accessed that object because MainActivity is derived from BaseActivity?

Upvotes: 1

Views: 203

Answers (1)

David Medenjak
David Medenjak

Reputation: 34522

Dagger will inject any annotated fields and methods of the declared parameter type and its supertypes. You can also read about it on the JavaDoc:

Members-injection methods

Members-injection methods have a single parameter and inject dependencies into each of the Inject-annotated fields and methods of the passed instance.

[...]

A note about covariance

While a members-injection method for a type will accept instances of its subtypes, only Inject-annotated members of the parameter type and its supertypes will be injected;

So if you have a SubActivity < BaseActivity < AppCompatActivity then declaring the method as inject(activity: BaseActivity) would only inject fields of BaseActivity and any supertypes, wheras inject(activity: SubActivity) will inject SubActivity as well as any parent/supertypes (BaseActivity in this example, your observed behavior).

Upvotes: 2

Related Questions