有关Dagger的Scope

本文详细解析了Dagger2中的依赖注入原理,包括不同作用域的使用方式及其对实例唯一性的影响,对比了Singleton与自定义Scope的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、假如Module中没有使用Scope,如@Singleton,则Component的定义的时候可以没有Scope

@Component(modules = {AppModule.class})
public interface AppComponent {


    Application getApplication();
}

@Module
public class AppModule {

    private Application application;

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

    @Provides
    public Application provideApplication() {
        return application;
    }


}
2、假如Module中有使用Scope,如@Singleton,而Component的定义的时候没有Scope,则会报错

如:

@Component(modules = {AppModule.class})
public interface AppComponent {


    Application getApplication();
}
@Module
public class AppModule {

    private Application application;

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

    @Provides
    @Singleton
    public Application provideApplication(){
        return application;
    }
}
这里Module里面使用了@Singleton而Component中没有,所以报错了。当我们在Component上面加上@Singleton错误消失


3、然后我们看看Singleton对赋值的影响

Component

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {


    Application getApplication();

    User getUser();

    User3 getUser3();
}

注意这里有getUser、getApplication等方法,如果这里不写的话,dagger自动生成的DaggerComponent中没有相应的provider,这个好像仅限于在application注册的Component,而在Activity中注册的不需要。

Module

@Module
public class AppModule {

    private Application application;

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

    @Provides
    @Singleton
    public Application provideApplication() {
        return application;
    }

    @Provides
    @Singleton
    User provideUser() {
        User user = new User();
        user.setId("1");
        user.setName("hello world");
        return user;
    }

    @Provides
    User3 provideUser3() {
        User3 user = new User3();
        user.setId("1");
        user.setName("hello world");
        return user;
    }
}

我们一个设置Singleton,一个没有,然后在两个Activity中注入

首先是第一个Activity

public class MainActivity extends BaseActivity {

    @Inject
    User user20;
    @Inject
    User user21;
    @Inject
    User3 user32;
    @Inject
    User3 user31;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        Intent i = new Intent(this, MainActivity2.class);
        startActivity(i);
    }

    @Override
    protected void setupActivityComponent(AppComponent appComponent) {
        DaggerMainActivityComponent.builder()
                .appComponent(appComponent)
                .mainActivityModule(new MainActivityModule(this))
                .build()
                .inject(this);

    }


}

@ActivityScope
@Component(modules = {MainActivityModule.class},dependencies = AppComponent.class)
public interface MainActivityComponent {
    MainActivity inject(MainActivity mainActivity);


}

public class MainActivityModule {

    private MainActivity mainActivity;

    public MainActivityModule(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }


    @Provides
    @ActivityScope
    MainActivity provideMainActivity() {
        return mainActivity;
    }


}
这里注意dependencies 不能是Module,如果改成Module的话会提示providerUser访问权限问题,但当我们改为public后会发现provider每次实例化都会调用该方法,实例化一个新的变量。

这里如果dependencies 是Component,我们的MainActivityComponent 的Scope不能是Singleton,他依赖的Module也不能是Singleton,而且一个Component的Scope只能有一个。

我们调试可以看到各个变量的值

可以看到User的两个变量值是一样的,而User3不一样,可以看到Singleton起作用了

然后这里我们会跳转到MainActivity2

public class MainActivity2 extends BaseActivity {

    @Inject
    User user20;
    @Inject
    User user21;
    @Inject
    User3 user32;
    @Inject
    User3 user31;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        ButterKnife.inject(this);

    }

    @Override
    protected void setupActivityComponent(AppComponent appComponent) {
        DaggerMainActivityComponent2.builder()
                .appComponent(appComponent)
                .mainActivityModule2(new MainActivityModule2(this))
                .build()
                .inject(this);

    }

}
这里跟MainActivity代码基本是一样的

我们看下他们的值

User还是前面的值,而User3都变化了

所以以通过在Application中提供的Singleton类型的provider起到了全局值唯一的作用。

我们看下User 的provider的实现

从这里可以看到User是从appComponent中去取的

userProvider是通过ScopedProvider去创建的,最终调用的get

这里可以看到我们是通过单实例实现的,这里provider是唯一的,provider里面提供的实例也是唯一的,所以整个应用是唯一的,也只有在Application中定义的Component才是全局唯一的,而我们通过自定义的Scope由于Provider是在属于的Component中初始化的,所以只在当前的Component是唯一的。在其他Component又会重新初始化provider.


4、然后我们自定义一个Scope MyScope

@Scope
@Retention(RUNTIME)
public @interface MyScope {
}

@MyScope
@Component(modules = {MainActivityModule.class}, dependencies = CommonModule.class)
public interface MainActivityComponent {
    MainActivity inject(MainActivity mainActivity);


}

@Module
public class CommonModule {


    @Provides
    @MyScope
    User2 provideUser2() {
        return new User2();
    }


}
@Module
public class MainActivityModule {

    private MainActivity mainActivity;

    public MainActivityModule(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }


    @Provides
    @MyScope
    MainActivity provideMainActivity() {
        return mainActivity;
    }


}


可以看到,在Activity内部,是同一个实例,在不同的activity是不同的实例



这里可以看到,他们的provider是不一样的,是各自在各自的Component中生成的,但是他们的provider都是通过ScopedProvider生成的,所以在同一个Activity中是一样的实例
这里我们换成Singleton也是一样的,因为生成了两个provider,只是在各自的Component是单实例的







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值