精华内容
下载资源
问答
  • Dagger

    2019-10-24 18:26:35
    Dagger
  • dagger

    2017-04-18 16:34:44
    优秀文章 http://www.jianshu.com/p/7505d92d7748 ...square维护的dagger分支 https://github.com/square/dagger Google维护的dagger分支 https:
    展开全文
  • Dagger A fast dependency injector for Java and Android. Dagger is a compile-time framework for dependency injection. It uses no reflection or runtime bytecode generation, does all its analysis at ...
  • Dagger demo

    2017-05-24 17:03:31
    Dagger demo,亲测可以运行。
  • Google Dagger 2(演示) 通过测试生产代码:) 适用于Java和Android的完全静态的编译时依赖项注入框架。 组态 build.gradle应用程序模块级别 dependencies { .. . implementation ' ...
  • dagger2 视频

    2017-11-29 14:34:12
    dagger2 视频 dagger2 视频 dagger2 视频 dagger2 视频
  • Dagger2Application:Dagger2上的POC项目
  • Introduce dagger

    2020-12-27 10:39:02
    <div><p>Really excited to finally introduce dagger to our app. #890 <p>This PR simply introduces dagger, a lot of <code>CommonsApplication</code> usage can be reduced by replacing it with DI. <p>Test...
  • Dagger2-源码

    2021-03-08 23:38:40
    Dagger2
  • 更新:最新的Dagger 2.11提供了一些帮助程序类。 出以获取更新的简化用法。 示例项目,以演示如何使用最新Dagger 的新模块。 以及。 还显示了和在侧面的设置。 显示一些 :red_heart: 动机 现在,您也许可以从...
  • Dagger例子

    2015-08-28 12:51:59
    Dagger实例讲解;Dagger 是一种android平台的依赖注入框架,是有一家专注于移动支付的公司,Square公司推出的库,这家公司也推出了其他在Android开发中常用库:otto,okhttp,retrofit等等,这些在接下的博文中会...
  • Dagger2.1不是Dagger2

    2018-08-21 19:02:54
    在学习android architecture components(简称acc)时下载了google官方demo,demo里有一部分是关于dagger+mvvm(mvp)+acc的,本以为阅读起来没有压力但结果却是一脸懵逼,是的,dagger的写法以及注解完全陌生。...

    一、前言

    在学习android architecture components(简称acc)时下载了google官方demo,demo里有一部分是关于dagger+mvvm(mvp)+acc的,本以为阅读起来没有压力但结果却是一脸懵逼,是的,dagger的写法以及注解完全陌生。难道dagger更新了?本着落后就要挨打的原则去google了一番,发现国内资料通篇都是dagger原本的用法,并没有找到我需要的。最后终于在国外网站找到了一篇dagger2.1新用法的介绍,配合dagger官网终于了解了一二,这也坚定了我从头写一篇Dagger文章的决心。

    本文适合人群:1、从未了解过dagger,2、仅简单使用API但不了解为何这样使用,3、可以很好的使用并理解dagger,仅需了解新版本(可以直接跳到第四部分)

    二、 Dependency Injection(DI)

    翻译成中文也就是依赖注入,我们先用一个很简单的例子来了解一下

        class Clothes {
            final int Defense = 5;
        }
    
        class Pants {
            final int Defense = 10;
        }
    
        class hero {
            
            void printDefense() {
                Clothes clothes = new Clothes();
                Pants pants = new Pants();
                
                System.out.print("您的角色拥有防御值: "+clothes.Defense + pants.Defense);
            }
        }

    这是一段很简单的代码,初始化角色时,拥有衣服裤子两件装备。但仔细查看,在hero类里创建了clothes和pants两个类,造成了耦合,当你修改clothes或pants时很可能影响到hero类。所以我们通常会将上述代码优化如下:

     class hero {
            private Clothes clothes;
            private Pants pants;
    
            public hero(Clothes clothes, Pants pants) {
                this.clothes = clothes;
                this.pants = pants;
            }
    
            void printDefense() {
                System.out.print("您的角色拥有防御值: "+clothes.Defense + pants.Defense);
            }
        }

    没错放到构造方法里,这就是'依赖注入'了,hero依赖了clothes和pants,同样的,set方法也可以进行依赖注入。大家是不是在不知不觉中也使用过类似的方式呢:)

    对比一下两种方式,前者的缺点如下:

    1、clothes和pants无法重用,降低了代码的重用性

    2、增加了代码的耦合性,一旦clothes和pants更改可能需要修改hero类很多地方

    3、很难进行单元测试

     

    好的,接下来我们就开始用依赖注入的方法创建hero

        public static void main(String[] args){
            Clothes clothes = new Clothes();
            Pants pants = new Pants();
    
            Hero hero = new Hero(clothes, pants);
            hero.printDefense();
        }

    这样子看起来没什么大问题,但是当依赖多了,或者依赖也依赖了其他依赖,就会相当臃肿。有点绕吗?没关系我们看代码:

    
        public static void main(String[] args) {
            Color red = new Color();
            Clothes clothes = new Clothes(red);
            Pants pants = new Pants();
            Shoes shoes = new Shoes();
            Hat hat = new Hat();
    
            ....
    
            Hero hero = new Hero(clothes, pants, shoes, hat, ....);
            hero.printDefense();
        }

    上面的代码中Clothes又依赖了Color,说不定Color又可能会依赖些什么,加上下面的Pants、Shoes、hat......等等,构造我们的Hero需要太多依赖,这样我们使用hero时就非常不方便,主方法就会越来越难以维护。

    三、Dagger基本使用

    这样,Dagger就孕育而生了,他是一个DI框架,会让我们的依赖注入工作显得非常轻松。自动生成依赖,而我们只需要添加注解即可。

    我们用Dagger的方式来重写上面的代码:

    
    class Clothes {
        final int Defense = 5;
    
        @Inject
        public Clothes() {
        }
    }
    
    class Pants {
        final int Defense = 10;
    
        @Inject
        public Pants() {
        }
    }
    
    class Hero {
        private static final String TAG = "Hero";
        private Clothes clothes;
        private Pants pants;
    
        @Inject
        public Hero(Clothes clothes, Pants pants) {
            this.clothes = clothes;
            this.pants = pants;
        }
    
        public void printDefense() {
            Log.e(TAG, "您的角色拥有防御值: " + (clothes.Defense + pants.Defense));
        }
    }

    是的,就是这么简单,只需要添加@Inject注解,Dagger就能帮我们自动构建Hero对象,当我们使用时就像这样:

    Component
    interface HeroComponent {
        Hero getHero();
    }
    
    
    
    
        public static void main(String[] args){
    //        Clothes clothes = new Clothes();
    //        Pants pants = new Pants();
    
    //        Hero hero = new Hero(clothes, pants);
    //        hero.printDefense();
    
    
            HeroComponent component = DaggerHeroComponent.create();
            Hero hero = component.getHero();
            hero.printDefense();
        }

    我们来梳理一下:

    1、首先创建一个component接口并添加@component注解,添加获取Hero的方法

    2、给Hero构造方法添加@Inject注解,表示需要自动生成该类

    3、给依赖类添加@Inject,表示改类也需要自动生成,如此递归添加直到所有依赖都能自动生成

    4、构建项目(必须先构建,Dagger会帮你生成一些辅助类),使用名为‘Dagger+YourComponent’的类创建Hero对象

    5、愉快的使用吧!

    这样一来无论Hero需要多少依赖,我们都可以很简单的生成,不会造成类的臃肿和耦合,使用Hero时不用关心依赖从哪里来,怎么来的,就算Hero或依赖构建方式改变,也不需要修改调用的main函数,很好的解耦。

    这时有些童鞋就会问了,如果我需要使用类似Retrofit、OkHttp之类的三方库,而我们却无法去库里添加@Inject注解,该怎么办?没关系,Dagger同样为大家准备了对策:@Module、@Provides

    @Module:类似一个仓库,提供Retrofit之流的实例

    @Provides:仓库里具体产品的标志,表示该产品对外提供

    @Module
    public class MyModule {
        
        @Provides
        public Retrofit ProvideRetrofit() {
            return new Retrofit.Builder()
                    .baseUrl("www.google.com")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(setupClient())
                    .build();
        }
    }

    这样就写好了一个提供Retrofit的方法,我们还需要将module提交到component:

    Component(modules = MyModule.class)
    interface HeroComponent {
        Hero getHero();
        Retrofit getRetrofit();
    }
    

    这样,我们就可以愉快的使用Retrofit了,使用方式和Hero一样,我就不累述了。

    关于其他API大家可以查阅资料,本文重在思路介绍。

    建议初学者在阅读以下内容前先了解更多Dagger2的使用,推荐文章:给初学者的Dagger2

    因为以下内容仅适合使用过Dagger2的童鞋了!!!

    四、Dagger&Android

    打起精神,重点来了!!

    在讲解重点之前,我们先来看一段代码:

    ((MyApplication) getApplication())
            .getAppComponent()
            .myActivity(new MyActivityModule(userId))
            .build()
            .inject(this);

    在熟悉使用过Dagger2的coder眼中,这段代码几乎贯穿了整个应用程序,每一个activity都会调用同样的代码,相信大家也想尽办法去优化该段代码,包括将其放入Base中或者做了各种各样的封装,可能都不太尽人意(至少笔者没有找到最优解-_-)。

    没错!官方这次升级完美的解决了该问题,以前的实现方式我就不多说了,直接讲述新版本方案。

    我先按流程走一遍,让大家熟悉熟悉:

    1、老规矩,gradle添加依赖

        implementation 'com.google.dagger:dagger-android:2.15'
        implementation 'com.google.dagger:dagger-android-support:2.15' // if you use the support libraries
        annotationProcessor 'com.google.dagger:dagger-android-processor:2.15'
        annotationProcessor 'com.google.dagger:dagger-compiler:2.15'
    

    笔者写的时候最新版为2.15,大家使用时可以更换为官方最新版。

    2、创建AppComponent

    @Component(modules = {
            AndroidSupportInjectionModule.class,
            AppModule.class,
            ActivityBuilder.class})
    public interface AppComponent  extends AndroidInjector<MyApplication> {
    
        @Override
        void inject(MyApplication app);
    
        @Component.Builder
        interface Builder {
            @BindsInstance
            Builder application(Application application);
    
            AppComponent build();
        }
    }
    @Component.Builder:自定义component构造器.如果看过Dagger2源码的童鞋应该知道component是用Builder模式创建的,而这里提供了一个自定义构造器。目前先不管,你甚至可以删除这个Builder都没有影响,Dagger会自动生成,这里我只是想展示一下这个注解

    继承了AndroidInjector类,重写了他的Inject方法,这个方法必须写,初始化AppComponent用。

    @Component(modules = {
            AndroidSupportInjectionModule.class,
            AppModule.class,
            MainActivityModule.class})

    Component注解里添加了需要使用到的Module

    AndroidSupportInjectionModule.class:这是Dagger2.1初始化必须的module,由Dagger内部完成,用于提供各种AndroidInjector,我们只需要固定加上即可
    AppModule.class:用于Application需要初始化提供的全局module,比如刚刚提到的Retrofit、Okhttp等全局对象
    ActivityBuilder.class:这就是我们Activity所需的Module了

    前两者我们先不关注,重点看看ActivityBuilder,这和我们以前的使用方式就不大相同了,先来看看他的实现。

    3、创建ActivityBuilder

    @Module
    public abstract class ActivityBuilder {
    
        @Binds
        @IntoMap
        @ActivityKey(MainActivity.class)
        abstract AndroidInjector.Factory<? extends Activity> bindMainActivity(MainActivityComponent.Builder builder);
    
    }

    这里是所有Activity(Fragment等)的Component.builder的集合,需要添加@Binds @IntoMap @ActivityKey注解,暂且不管他们的具体作用,只需要了解@Binds就类似于@Provides就可以了。这个类的作用就是让Dagger知道我们所有的使用地。

    4、创建MainActivityComponent

    @Subcomponent(modules = {MainActivityModule.class})
    public interface MainActivityComponent extends AndroidInjector<MainActivity> {
        @Subcomponent.Builder
        public abstract class Builder extends AndroidInjector.Builder<MainActivity> {
        }
    }

    需要使用@Subcomponent注解,所以不需要再像以前写Inject之类的方法,modules和以前一样

    值得一说的就是内部类Builder,是固定写法,和第三步配套使用。

    5、创建MainActivityModule

    @Module
    public class MainActivityModule {
        @Provides
        MainView provideMainView(MainActivity mainActivity){
            return mainActivity;
        }
        @Provides
        MainPresenter provideMainPresenter(MainView mainView, ApiService apiService) {
            return new MainPresenter(mainView, apiService);
        }
    }
    

    这个也和以前一样,提供需要的依赖

    不要忘记在Appmodule里添加subComponent注释,如果Activity多了这里就会添加非常多的XXComponent

    @Module(subcomponents = {MainActivityComponent.class,XX,XX,XX.....})
    public abstract class AppModule {
    
    }
    

    6、初始化Application

    public class MyApplication extends Application implements HasActivityInjector {
        @Inject
        DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
    
        @Override
        public void onCreate() {
            super.onCreate();
            DaggerAppComponent.builder().application(this).build().inject(this);
        }
    
        @Override
        public AndroidInjector<Activity> activityInjector() {
            return dispatchingAndroidInjector;
        }
    }

    继承HasActivityInjector,重写activityInjector方法,返回一个DispatchingAndroidInjector

    然后在oncreate里初始化

    7、MainActivity使用

    public class MainActivity extends AppCompatActivity implements MainView {
       
        @Inject
        MainPresenter presenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            AndroidInjection.inject(this);
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            presenter.loadMain();
        }
    
        @Override
        public void onMainLoaded() {
            ((TextView)findViewById(R.id.hw)).setText("hello Dagger2.1");
        }
    }

    调用AndroidInjection.inject(this)即可,无须再调用一长串Dagger链。

    到这里,初步使用就已经结束了,看到这里可能会觉得‘尼玛,好像更麻烦了’,‘绕来绕去头都大了’的感慨,没错,确实是更麻烦了,不过别着急,前面我只是希望大家看看最基础的用法,然后再介绍更简洁的方式,不然大家很可能只会用而不知道其中的来历。

    优化一:继承DaggerApplication、DaggerActivity等类

    大家应该还记得刚刚提到的Application类的实现,需要:

    1、继承HasActivityInjector,2、重写activityInjector方法,3、返回一个DispatchingAndroidInjector

    其实不仅是Application,在Activity、Fragment里只要有subcomponent就必须要实现类似的类,举个栗子:

    一个Activity里有一个Fragment,fragment需要依赖注入,这时候Activity就必须

    1、继承HasFragmentInjector, HasSupportFragmentInjector

    2、重写supportFragmentInjector、fragmentInjector方法

    3、返回DispatchingAndroidInjector<Fragment>、DispatchingAndroidInjector<android.app.Fragment>

    这样的话将会非常麻烦而且重复,但只需要继承了DaggerApplication、DaggerActivity,一切都变得简单了,Dagger2.1都帮你搞定了。这里放出优化后的Application:

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

    对比上面的是不是简单了很多,其实Activity会更明显,而且每个Activity节省的代码加起来是不可计数的,就留给大家自己去尝试了。

    优化二:使用注解@ContributesAndroidInjector

    这是Dagger2.1最强大的注释,会帮助你节省数以万计的代码,可能你看到之前的介绍还并不希望升级/使用Dagger2.1,但是用了他之后你就会爱上他。

    还记得我们的ActivityBuilder吗?多了@Binds @IntoMap @ActivityKey注解,可能之前我们根本没有用到过,并用他们关联到Component.Builder,同样是重复的工作。利用@ContributesAndroidInjector可以省略这一切,于是我们的ActivityBuilder就变成了这样:

    @Module
    public abstract class ActivityBuilder {
    
        @ContributesAndroidInjector(modules = MainActivityModule.class)
        abstract MainActivity bindMainActivity();
    
        @ContributesAndroidInjector(modules = {SecondActivityModule.class, SecondFragmentProvider.class})
        abstract SecondActivity bindSecondActivity();
    }

    而我们的MainActivityComponent类就可以删掉了,是的没错,直接删掉吧!Dagger会帮我们自动生成,这样每个Activity只需要对应一个Module即可,还记得以前每个Activity对应一个Component和一个Module吗?

    AppModule也可以不需要列出所有Module了,直接删掉

     

    五、结语

    通过优化后,你的代码已经非常简洁了,大家可以尝试用新版的Dagger来写,然后对比以前的方式,你一定会迫不及待使用新版的。

    本文完整代码已经提交到GitHub

    分为两个分支,master中使用了初始版,complete中使用了简洁的方式,并利用Dagger实现了MVP模式以及绑定Fragment的方式,大家一定要下载阅读,这样更有利于理解。

    当然如果觉得有用的话记得点一下star,这是对作者的最大鼓励。

    地址:https://github.com/mrqatom/DaggerInjection

     

    下期预告:@Binds详细讲解、Dagger2.1源码讲解

     

    参考文档:

    https://medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe

    https://medium.com/@harivigneshjayapalan/dagger-2-for-android-beginners-dagger-2-part-i-f2de5564ab25

    https://google.github.io/dagger/android

    展开全文
  • Dagger2 demo

    2017-09-18 22:31:30
    自己关于Dagger2的理解,还有一些常用Dagger2的注解。自己关于Dagger2的理解,还有一些常用Dagger2的注解。
  • Dagger Note

    2020-11-29 11:34:58
    <p>Note: Generating a MembersInjector or Factory for com.artemzin.qualitymatters.QualityMattersApp. Prefer to run the dagger processor over that class instead. <p>Should we pay attention to this one?...
  • Dagger2Demo

    2018-06-30 17:12:50
    介绍了Dagger2的常用使用方法,和演示案例,提供Dagger2的入门学习方法。
  • 刀鞘::dagger:可视化Dagger 2依赖图的工具
  • 告别Dagger2模板代码:Dagger Android使用详解

    万次阅读 多人点赞 2017-08-22 20:38:29
    概述,学Dagger2-Android的理由Dagger2的窘境在使用Dagger2进行Android开发时,不可避免的问题是我们需要实例化一些Android系统的类,比如Activity或者Fragment。最理想的情况是Dagger能够创建所有需要依赖注入的...

    概述,学Dagger2-Android的理由

    Dagger2的窘境

    在使用Dagger2进行Android开发时,不可避免的问题是我们需要实例化一些Android系统的类,比如Activity或者Fragment。最理想的情况是Dagger能够创建所有需要依赖注入的对象,但事实上,我们不得不在容器的声明周期中声明这样的代码:

    public class FrombulationActivity extends Activity {
      @Inject Frombulator frombulator;
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // DO THIS FIRST. Otherwise frombulator might be null!
        ((SomeApplicationBaseType) getContext().getApplicationContext())
            .getApplicationComponent()
            .newActivityComponentBuilder()
            .activity(this)
            .build()
            .inject(this);
        // ... now you can write the exciting code
      }
    }

    这样的确可以实现Android的依赖注入,但还有两个问题需要我们去面对:

    1.即使Dagger使我们的代码耦合性更低,但是如果要面临重构,我们仍然不得不去面对每个Activity中这样数行需要我们「复制」+「粘贴」的代码,这会给我们的重构带来一定的难度(试想一下,如果我们的应用有数十个乃至上百个这样的Activity或者Fragment容器,我们的重构计划,首先就要面对这样数百行的代码)。
    并且随着新的开发人员加入(他们也许并不知道这些代码的意义,但是他们会复制粘贴),越来越少的人知道这些代码都干了些什么。
    2.更重要的是,它要求注射类型(FrombulationActivity)知道其注射器。 即使这是通过接口而不是具体类型完成的,它打破了依赖注入的核心原则:一个类不应该知道如何实现依赖注入。

    瑕不掩瑜!

    诚如标题所言,虽然Dagger2在Android开发中有一些问题,但是它强大的功能依然使得开发人员趋之若鹜,无数的工程师们尝试弥补Dagger的这个问题,于是Dagger2-Android,基于Dagger2,应用于Android开发,由google开发的的拓展库应运而生。

    本文结构

    1. 概述,我们学Dagger2-Android的理由
    2. 应用,Dagger2-Android入门Demo
    3. 重构,基于google官方demo的优化尝试
    4. 源码分析,知其然亦要知其所以然
    5. 总结

    「提示」本文篇幅较长,且和Dagger2的使用有一定的区别(需要额外的学习成本),若您觉得本文尚可,建议收藏慢慢阅读

    「知识储备」本文可能需要您对Dagger2有足够的了解

    如果您对Dagger2一些知识点不熟悉,可以尝试看一下笔者的Dagger2相关文章:

    Dagger2使用详解(四)Scope注解的使用及源码分析

    Dagger2使用详解(三)进阶篇 MVP架构下的使用

    Dagger2使用详解(二)Module&Component源码分析

    Dagger2使用详解(一)基础使用

    应用,Dagger2-Android入门Demo

    1.环境&依赖

        annotationProcessor 'com.google.dagger:dagger-compiler:2.11' //一定要添加dagger2的annotationProcessor!
        compile 'com.google.dagger:dagger-android:2.11'
        compile 'com.google.dagger:dagger-android-support:2.11' // if you use the support libraries
        annotationProcessor 'com.google.dagger:dagger-android-processor:2.11
    

    2.Demo结构分析

    首先我们先看看Demo效果

    这里写图片描述

    结构如下:

    这里写图片描述

    可以看到,我们在MainActivity中需要通过依赖注入,获得4个对象,同时MainPresenter和MainModel也同样得到了实例化,我们先看下MVP这个架构中三个成员的代码:

    3.MVP基本代码

    MainActivity相关代码

    MainActivity代码:

    public class MainActivity extends BaseActivity implements MainContract.View {
    
        @Inject
        String className;
        @Inject
        Student student;
        @Inject
        SharedPreferences sp;
        @Inject
        MainPresenter presenter;
    
        @BindView(R.id.tv_content)
        TextView tvContent;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
    
            //下面这行代码把所有实例化的对象展示在界面中
            tvContent.setText(className + "\n" +
                    student.toString() + "\n" +
                    sp.toString() + "\n" +
                    presenter.toString());
        }
    
         //省略其他代码

    显然,从结果来看,我们根本没有在Activity中添加上文所述的模板代码:

        //就是这些,模板代码
        ((SomeApplicationBaseType) getContext().getApplicationContext())
            .getApplicationComponent()
            .newActivityComponentBuilder()
            .activity(this)
            .build()
            .inject(this);

    MainPresenter代码:

    public class MainPresenter implements MainContract.Presenter {
    
        private final MainActivity view;
        private final MainModel model;
    
        @Inject
        public MainPresenter(MainActivity view, MainModel model) {
            this.view = view;
            this.model = model;
        }
    
        //省略其他代码
    }
    

    MainModel代码:

    public class MainModel implements MainContract.Model {
    
        @Inject
        public MainModel() {
        }
    
       //省略其他代码
    }

    和Dagger2的使用没有区别,其根本原理,都是通过@Inject注解,使Dagger2自动生成对应的工厂类,以提供MainPresenter和MainModel的实例。

    SecondActivity代码

    和MainActivity基本一样,为了简便我们只注入了一个String,用来展示类名(请参照上面的gif图):

    public class SecondActivity extends BaseActivity {
    
        @Inject
        String className;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
            TextView tv = (TextView) findViewById(R.id.tv_content);
            tv.setText(className);
        }
    }

    可以看到,我们依然没有添加冗余的模板代码,试想,一个app中这样几十个Activity容器都不需要这样的模板代码,我们的工作量确实减少了很多,同时,也达到了我们的目的,即:

    依赖注入的核心原则:一个类不应该知道如何实现依赖注入。

    实际上,我们只是在BaseActivity中,添加了这样一行代码,就实现了我们想要的效果

    public class BaseActivity extends AppCompatActivity{
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            AndroidInjection.inject(this);  //一处声明,处处依赖注入
            super.onCreate(savedInstanceState);
        }
    }
    

    接下来,让我们看看Dagger2-Android 的Module和Component怎么写

    参考:谷歌官方Demo https://google.github.io/dagger//android.html

    4.Module和Component

    首先我们先声明对应Activity的Module和Component:

    MainActivity依赖配置

    我们声明Subcomponent,其关联的module可以提供MainActivity所需要的所有依赖的实例。

    @Subcomponent(modules = {
            AndroidInjectionModule.class,
            MainActivitySubcomponent.SubModule.class
    })
    public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
    
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<MainActivity> {
        }
    
        @Module
        class SubModule {
    
            @Provides
            String provideName() {
                return MainActivity.class.getName();
            }
    
            @Provides
            Student provideStudent() {
                return new Student();
            }
    
            @Provides
            SharedPreferences provideSp(MainActivity activity) {
                return activity.getSharedPreferences("def", Context.MODE_PRIVATE);
            }
    
            @Provides
            MainModel provideModel() {
                return new MainModel();
            }
        }
    }

    然后我们创建MainActivityModule

    @Module(subcomponents = MainActivitySubcomponent.class)
    public abstract class MainActivityModule {
    
        @Binds
        @IntoMap
        @ActivityKey(MainActivity.class)
        abstract AndroidInjector.Factory<? extends Activity>
        bindMainActivityInjectorFactory(MainActivitySubcomponent.Builder builder);
    
    }

    ok,这样MainActivity的相关依赖注入配置完毕。

    SecondActivity依赖配置

    同理,Subcomponent代码如下:

    @Subcomponent(modules = {
            SecondActivitySubcomponent.SubModule.class,
            AndroidInjectionModule.class,
    })
    public interface SecondActivitySubcomponent extends AndroidInjector<SecondActivity> {
    
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<SecondActivity> {
        }
    
        @Module
        class SubModule {
            @Provides
            String provideName() {
                return SecondActivity.class.getName();
            }
        }
    }

    然后是Model

    @Module(subcomponents = SecondActivitySubcomponent.class)
    public abstract class SecondActivityModule {
    
        @Binds
        @IntoMap
        @ActivityKey(SecondActivity.class)
        abstract AndroidInjector.Factory<? extends Activity>
        bindSecondActivityInjectorFactory(SecondActivitySubcomponent.Builder builder);
    
    }
    

    各个模块配置完毕,接下来我们将上述的Module组合起来即可:

    全局依赖配置

    我们先声明我们的Application类,然后一定要记得添加到清单文件中:

    public class MyApplication extends Application implements HasActivityInjector {
    
        @Inject
        DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
    
        @Override
        public void onCreate() {
            super.onCreate();
            //DaggerMyAppComponent.create().inject(this);
        }
    
        @Override
        public AndroidInjector<Activity> activityInjector() {
            return dispatchingAndroidInjector;
        }
    
    }

    请注意,我们在这里做了几件事:

    1.实现HasActivityInjector接口

    2.实现HasActivityInjector接口的activityInjector()方法

    3.声明一个泛型为Activity的DispatchingAndroidInjector成员变量并在activityInjector()方法中返回

    这里我们注释掉了一行代码,因为我们要先写AppComponent接口,然后编译,才能让编译器自动生成DaggerMyAppComponent类。

    @Component(modules = {
            AndroidInjectionModule.class,
            AndroidSupportInjectionModule.class,
            MainActivityModule.class,
            SecondActivityModule.class
    })
    public interface MyAppComponent {
    
       void inject(MyApplication application);
    }

    请注意,我们在这里做了几件事:

    1.在这个Component中添加了 AndroidInjectionModule 和 AndroidSupportInjectionModule

    2.同时添加了MainActivityModule 和 SecondActivityModule的依赖

    3.声明注入方法inject,参数类型为MyApplication

    好的,所有配置全部结束,我们使用ctrl+F9(Mac:cmd+F9)进行编译,然后打开MyApplication中注释的那行代码,运行app,依赖注入成功,如上文gif图所示。

    5.除Activity之外,Dagger-Android还提供了Fragment,BroadCast,Service等其他组件的注入方式,详情请参照官方网站,本文不赘述。

    https://google.github.io/dagger//android.html

    6.注意

    如果您按照本文中的代码实现,并没有得到对应的效果或者编译错误,请仔细检查是否严格按照本文的步骤进行编码,如果还有问题,建议您直接拉到本文最下方,下载源码查看。

    重构,基于google官方demo的优化尝试

    1.还有一些冗余代码

    上述章节中的使用方式基本是按照谷歌官方的guide进行的依赖注入,实际上个人认为还有几点可以优化:

    1.多余的ActivityModule

    请参照上文的MainActivityModule和SecondActivityModule,实际上从根本上来说,也类似模板代码,当界面多了,会生成大量的java文件

    2.多余的Subcomponent
    同理,太多了。

    3.越来越庞大的AppComponent
    当Activity越来越多,AppComponet中的注解会变成这样:

    @Component(modules = {
            AndroidInjectionModule.class,
            AndroidSupportInjectionModule.class,
            MainActivityModule.class,
            SecondActivityModule.class
            ...
            ...//中间省略不知道多少行
            XXActivityModule.class
    })

    我们来看看目前的结构:
    这里写图片描述

    可以看到,很冗余,实质上,表面上的注入器(Appcomponent),和对象的提供者(MainSubComponent.SubModule)两者起到了至关重要的作用,而Module和SubComponent作用不大。

    2.假设

    于是我们联想,我们可不可以改变结构成这样呢:

    这里写图片描述

    简述如下:

    1.AppComponent的module:AllActivityModule,其负责所有ActivityModule实例的管理

    2.BaseActivityComponent为AllActivityModule的subcomponent,管理了提供各activity所需对象的module

    3.MainActivityModule 负责提供所有对应Activity所需要对象实例的提供。

    3.实装

    首先,创建BaseActivityComponent,并将所有的ActivitySubcomponent删除:

    @Subcomponent(modules = {
            AndroidInjectionModule.class,
    })
    public interface BaseActivityComponent extends AndroidInjector<BaseActivity> {
        //每一个继承BaseActivity的Activity,都共享同一个SubComponent
        @Subcomponent.Builder
        abstract class Builder extends AndroidInjector.Builder<BaseActivity> {
        }
    
    }

    然后我们将对应的对象提供放到ActivityModule里:

    MainActivityModule:

    @Module
    public class MainActivityModule {
    
        @Provides
        static String provideName() {
            return MainActivity.class.getName();
        }
    
        @Provides
        static SharedPreferences provideSp(MainActivity activity) {
            return activity.getSharedPreferences("def", Context.MODE_PRIVATE);
        }
        //其他对象的提供 省略
    }

    SecondActivityModule:

    @Module
    public abstract class SecondActivityModule {
    
        @Provides
        static String provideName() {
            return SecondActivity.class.getName();
        }
    
    }

    那么问题来了,我们原本放在这里面的这些代码怎么办呢,例如:

        @Binds
        @IntoMap
        @ActivityKey(SecondActivity.class)
        abstract AndroidInjector.Factory<? extends Activity>
        bindSecondActivityInjectorFactory(SecondActivitySubcomponent.Builder builder);

    新建AllActivitysModule,并统统放入其中统一管理:

    @Module(subcomponents = {
            BaseActivityComponent.class
    })
    public abstract class AllActivitysModule {
    
        @ContributesAndroidInjector(modules = MainActivityModule.class)
        abstract MainActivity contributeMainActivitytInjector();
    
        @ContributesAndroidInjector(modules = SecondActivityModule.class)
        abstract SecondActivity contributeSecondActivityInjector();
    
    }

    这样,我们每次新建一个Activity,只需要统一在这里新建2行代码声明对应的Activity即可。

    对个人而言,这样的好处在于:
    1.每次不再需要额外声明一个SubCompoent,再次减少模板代码
    2.每个Activity的Module都放在同一个AllActivitysModule中进行统一管理,每次修改只需要修改这一个类即可
    3.每个Activity所单独需要的依赖,依然由各自的Module进行管理和实例化,依然没有任何耦合

    关于这两行代码的解释,请参考官网:https://google.github.io/dagger//android.html

    Pro-tip: If your subcomponent and its builder have no other methods or supertypes than the ones mentioned in step #2, you can use @ContributesAndroidInjector to generate them for you. Instead of steps 2 and 3, add an abstract module method that returns your activity, annotate it with @ContributesAndroidInjector, and specify the modules you want to install into the subcomponent. If the subcomponent needs scopes, apply the scope annotations to the method as well.

    @ActivityScope
    @ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ })
    abstract YourActivity contributeYourActivityInjector();

    最后修改AppComponent

    @Component(modules = {
            AndroidInjectionModule.class,
            AndroidSupportInjectionModule.class,
            AllActivitysModule.class    
    })
    public interface MyAppComponent {
    
        void inject(MyApplication application);
    }

    修改完毕,大功告成!

    好的,所有配置全部结束,我们使用ctrl+F9(Mac:cmd+F9)进行编译,然后打开MyApplication中注释的那行代码,运行app,依赖注入依旧成功。

    不同的是,这次我们的模板代码更少了。

    源码分析,知其然亦要知其所以然

    一路写下来,单单该库的使用,竟然洋洋洒洒竟然写了这么多,实在超出预料。

    // 源码分析,鉴于篇幅所限,准备另起一篇文章改日慢慢分析。 2017/8/22

    2017/8/30更新

    源码分析,鉴于篇幅所限,另起一篇文章,请阅读本文:

    Dagger-Android详解&源码分析

    总结

    看了这么多,有的朋友可能会看了几眼就不看了,也一定会有人觉得笔者啰嗦,文笔有限,但还是希望能够给大家提供一定的帮助,毕竟关于这个库,国内的中文相关资料实在有限,而Dagger依赖注入库的学习成本,也是出了名的高。

    最后提供一下本文demo源码连接:

    https://github.com/qingmei2/Sample_dagger2

    展开全文
  • Dagger.jar

    2017-01-23 10:07:55
    Dagger.jar
  • 匕首练习 Android Dagger + MVVM + RxJava实践
  • dagger2

    2020-02-11 17:01:10
    Dagger2是什么? Dagger2是一个通过Java注解的手段,省下大量new对象的代码,并达成解耦目的的框架。也就是老生常谈的依赖注入框架。 @Inject: 通常在需要依赖的地方使用这个注解。换句话说,你用它告诉Dagger这个...
  • Dagger2

    2018-07-27 00:02:25
    先导入依赖 compile 'com.google.dagger:dagger:2.7' ...Dagger2 依赖注入框架 在编译期间自动生成代码,负责依赖对象的创建。 依赖注入 依赖注入是一种面向对象的编程方式,它的出现就是为了降低耦...
  • Dagger示例项目展示如何使用新的dagger-android模块
  • Dagger2教程

    2018-09-07 18:23:28
    1.为什么要使用Dagger2.mp4 2.Dagger2的基本使用.mp4 3.模块化实现.mp4 4.创建和区分不同实例.mp4 5.Singleton 单例讲解.mp4 6.自定义Scope.mp4 7.SubCompnet和Lazy与Provider.mp4
  • Android代码-dagger

    2019-08-06 08:54:20
    Dagger 1 A fast dependency injector for Android and Java. Deprecated – Please upgrade to Dagger 2 Square's Dagger 1.x is deprecated in favor of Google's Dagger 2. Please see the migration guide for ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,127
精华内容 3,250
热门标签
关键字:

dagger