Android:Dagger2原理及使用详解(二)

目录

  • 一:Dagger2是什么?
  • 二:为什么要有Dagger2
  • 三:Dagger2如何使用
      1. 基本的概念
      1. 如何使用Dagger2
      1. 高级用法
      • (1)构造方法需要其他参数时候
      • (2) 模块之间的依赖关系
      • (3) @Named注解使用
      • (4) @Singleton注解
      • (5)自定义Scoped
      • (6)Subcomponent
      • (7)lazy 和 Provider
  • 四: MVP + Dagger2

3. 高级用法

(1)构造方法需要其他参数时候

怎么说呢,就和最来时的意思一样,

A a = new A(new B());
a.eat();

这种情况,如何使用Dagger2呢
肯定有小伙伴这么想

   @Provides
    A providerA() {
        return new A(new B());
    }

直接 new 一个B ,这样的使用方法,是不对的!!!!!!,不对的!!!!!!!,不对的!!!!!!!!!

正确的打开方式

这时候,我们什么都不用改,只需要在moudule中添加一个依赖就可以了

@Module
public class MainModule {

    /***
     * 构造方法需要其他参数时候
     *
     * @return
     */
    @Provides
    B providerB() {
        return new B();
    }

    @Provides
    A providerA(B b) {
        return new A(b);
    }
}

(2) 模块之间的依赖关系

模块与模块之间的联系

@Module (includes = {BModule.class})// includes 引入)
public class AModule {
    @Provides
    A providerA() {
        return new A();
    }
}

这样的话,Dagger会现在A moudule 中寻找对象,如果没找到,会去找module B 中是否有被Inject注解的对象,如果还是没有,那么GG,抛出异常

一个Component 应用多个 module
@Component(modules = {AModule.class,BModule.class})
public interface MainComponent {
    void inject(MainActivity activity);
}
dependencies 依赖其他Component
@Component(modules = {MainModule.class}, dependencies = AppConponent.class)
public interface MainConponent {
    void inject(MainActivity activity);
}

注意这里有坑,一下会讲解


(3) @Named注解使用

相当于有个表示,虽然大家都是同一个对象,但是实例化对象不同就不如

A a1 = new A();
A a2 = new A();

// a1  a2 能一样嘛
Module中 使用@Named注解
@Module
public class MainModule {

    private MainActivity activity;

    public MainModule(MainActivity activity) {
        this.activity = activity;
    }

    @Named("dev")
    @Provides
    MainApi provideMainApiDev(MainChildApi mainChildApi, String url) {
        return new MainApi(mainChildApi, activity,"dev");
    }

    @Named("release")
    @Provides
    MainApi provideMainApiRelease(MainChildApi mainChildApi, String url) {
        return new MainApi(mainChildApi, activity,"release");
    }

}
在Activity/Fragment中使用
public class MainActivity extends AppCompatActivity {

    @Named("dev")
    @Inject
    MainApi apiDev;

    @Named("release")
    @Inject
    MainApi apiRelease;

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

        DaggerMainComponent.builder()
                .mainModule(new MainModule(this))
                .mainChildModule(new MainChildModule())
                .build()
                .inject(this);
        apiDev.eat();
        apiRelease.eat();
        Log.i("TAG","apiDev--->" + apiDev);
        Log.i("TAG","apiRelease--->" + apiRelease);
    }

}
打印Log
07-14 01:46:01.170 2006-2006/? I/TAG: apiDev--->com.allen.rxjava.MainApi@477928f
07-14 01:46:01.170 2006-2006/? I/TAG: apiRelease--->com.allen.rxjava.MainApi@f2b291c

(4) @Singleton注解

单例模式,是不是超级方便,你想然哪个对象单例化,直接在他的Provider上添加@Singleton 就行了

例如

    @Singleton
    @Provides
    A providerA(B b) {
        return new A(b);
    }

注意: 第一个坑!!!
如果 moudule所依赖的Comonent 中有被单例的对象,那么Conponnent也必须是单例的

@Singleton
@Component(modules = {MainModule.class})
public interface MainConponent {
}

然后 在Activity中使用,直接打印a1 a2 的地址,

    @Inject
    A a2;
    @Inject
    A a1;

可以看到Log

12-30 01:32:58.420 3987-3987/com.allens.daggerdemo E/TAG: A1---->com.allens.daggerdemo.Bean.A@11fa1ba
12-30 01:32:58.420 3987-3987/com.allens.daggerdemo E/TAG: A1---->com.allens.daggerdemo.Bean.A@11fa1ba

不相信的小伙伴可以吧@Singleton去掉试试

现在我们完成了单例,然后做了一个事情,就是点击某个按钮,跳转到一个新的Activiry,两边都引用同样一个A 对象,打印A 的地址,

说一下,一个Conponent 可以被对个Activity/Fragment 引用,如

@Singleton
@Component(modules = {MainModule.class})
public interface MainConponent {
    void inject(MainActivity activity);
    void inject(TestAct activity);
}

上面与两个Activity, MainActivity 和 TestAct ,都引用相同的对象,答应地址看看

12-30 00:48:17.477 2788-2788/com.allens.daggerdemo E/TAG: A1---->com.allens.daggerdemo.Bean.A@11fa1ba
12-30 00:48:17.517 2788-2788/com.allens.daggerdemo E/TAG: A2---->com.allens.daggerdemo.Bean.A@4f81861

竟然不同,说好的单例呢

注意: 第二个坑,单例对象只能在同一个Activity中有效。不同的Activity 持有的对象不同

那有人就要问了,没什么办法么,我就想全局只要一个实例化对象啊? 办法肯定是有的,


(5) 自定义Scoped

/**
 * @作者 :  Android-SuperMan
 * @创建日期 :2017/7/14 下午3:04
 * @方法作用:
 * 参考Singleton 的写法
 * Scope 标注是Scope
 * Documented 标记在文档
 * @Retention(RUNTIME) 运行时级别
 */
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScoped {
}

首先想一下,什么样的对象,能够做到全局单例,生命周期肯定和APP 绑定嘛,这里我做演示,一个AppAip 我们要对这个对象,全局单例,所以二话不说,先给Application 来个全家桶,

Module
@Module
public class AppModule {

    @Singleton
    @Provides
    AppApi providerAppApi() {
        return new AppApi();
    }
}
Component
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    AppApi getAppApi();
}
Application
public class MyApp extends Application {

    private AppConponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppConpoment.create();
    }

    public AppConponent getAppComponent() {
        return appConponent;
    }
}

————————分割线————————

如果你看到了这里,觉得文章写得不错就给个关注呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!希望读到这的您能关注下我,以后还会更新技术干货,谢谢您的支持!

转发分享+关注,每天获取更多资料

Android架构师之路很漫长,一起共勉吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值