jangsunok
jangsunok

Reputation: 13

Android Dagger2

I am confused about Dagger2 in Android. I use two scope. @Singleton, @PerActivity

This is my Code. I simplyfy my code.

//ApplicationComponent.java
@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
    @Named("packageName") String packageName();
}


//ApplicationModule.java
@Module
public class ApplicationModule {  

    @Provides
    @Singleton
    public Context provideApplicationContext() {
        return MyApplication.getContext();
    }

    @Provides
    @Singleton
    @Named("packageName")
    public String providePackageName(Context context) {
        return context.getPackageName();
    }
}

//UserComponent.java
@PerActivity
@Component(modules = {UserModule.class})
public interface UserComponent {
    void inject(MainActivity activity);
}

//UserModule.java
@Module
public class UserModule {
    String packageName;

    public UserModule(String packageName) {
        this.packageName = packageName;
    }


    @Provides
    @PerActivity
    UserRepositoryImpl provideUserRepositoryImpl() {
        return new UserRepositoryImpl(packageName);
    }
}

for inject appVersion, packagename in UserModule

DaggerChatComponent.builder()
                .userModule(new UserModule(getApplicationComponent().packageName()))
                .build();

but it looks not great. how can i inject when use different Scope??

Upvotes: 0

Views: 261

Answers (1)

Jenison Gracious
Jenison Gracious

Reputation: 545

your ApplicationModule.java is correct

@Module
public class ApplicationModule {

    private Application application;

    public ApplicationModule(Application application){
        this.application = application;
    }

    @Provides
    @Singleton
    Context provideContext(){
        return application;
    }

    @Provides
    @Singleton
    @Named("packagename")
    public String providePackageName(Context context) {
        return context.getPackageName();
    }
}

and it's component class is also right ApplicationComponent.java

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {


    @Named("packagename") String providepackagename();
}

but in the UserModule.java you need not pass the package name object , dagger's object graph does this for you.

@Module
public class UserModule {


    public UserModule() {
    }


    @Provides
    @PerActivity
    UserRepositoryImpl provideUserRepositoryImpl(@Named("packagename") String packageName) {
        return new UserRepositoryImpl(packageName);
    }
}

and the next step is while writing the component class for this module add the application component as a dependency ie, your UserComponent.java looks like this

@PerActivity
@Component(dependencies = {ApplicationComponent.class},modules = {UserModule.class})
public interface UserComponent {

    void inject(MainActivity mainActivity);
}

with the activity scope as PerActivity.lava

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}

with this example UserRepositoryImpl.java as

class UserRepositoryImpl {

    private String packagename;

    public UserRepositoryImpl(String packagename){

        this.packagename = packagename;
    }

    String getPackagename(){
        return packagename;
    }
}

you can finally inject this in your activity.(MainActivity.java)

public class MainActivity extends AppCompatActivity {

    @Inject
    UserRepositoryImpl userRepository;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ApplicationComponent component=DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(getApplication())).build();
        UserComponent userComponent=DaggerUserComponent.builder().applicationComponent(component).userModule(new UserModule()).build();
        userComponent.inject(this);
        Log.e("name"," "+userRepository.getPackagename());
    }
}

Upvotes: 1

Related Questions