美文网首页程序员
Dagger2 Android --- 基础使用篇

Dagger2 Android --- 基础使用篇

作者: bf027edd3b22 | 来源:发表于2018-10-18 16:48 被阅读59次

    该文章默认你已经掌握了Dagger2的常规使用。

    如果对Dagger2的概念还不是很清楚,可以参考:

    Dagger Android产生的原因??

    1. 对象使用者如果需要使用 Inject 注解生成的对象,需要知道其注入器(比如:DaggerxxxComponent),它打破了依赖注入的原则:一个类不应该知道如何注入它。
    2. 随着项目代码的增多,类似 DaggerxxxComponent.buider().build().inject() 这样的模板代码也会越来越多,使得后期很难重构。

    Dagger2 2.1x新特性

    解决了Dagger2 2.10之前的两个明显的缺陷,被注入者不需要知道其注入者

    依赖

    //dagger2 依赖
    implementation 'com.google.dagger:dagger:2.16'
    //dagger2 android依赖,一般直接依赖dagger-android-support,其内部默认依赖了dagger-android
    //implementation 'com.google.dagger:dagger-android:2.16'
    //添加了android support的支持
    implementation 'com.google.dagger:dagger-android-support:2.16'
    //dagger注解处理器
    annotationProcessor 'com.google.dagger:dagger-compiler:2.16'
    //dagger android注解处理器 
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.16'
    

    使用步骤

    1. 被依赖类:在构造函数上使用@Inject注解声明
        public class Student {
        
            private String name;
        
            @Inject
            public Student() {
        
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
            
        }
    
    2. 使用依赖对象
        public class MainActivity extends AppCompatActivity {
        
            private static final String TAG = MainActivity.class.getSimpleName();
        
            @Inject
            Student student;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                
                Log.e(TAG, "student ---- " + student.toString());
            }
        }
    

    如果直接这样运行肯定是直接NullPoint,因为student还没有被注入到MainActivity之中。

    那Student对象又是如何注入的呢?

    3. 实现依赖对象和使用者的绑定
    1. 自定义Application继承DaggerApplication(注意导包,使用dagger.android.support.DaggerApplication)

      这一步是实现自动注入的前提

       public class DemoApp extends DaggerApplication {
           
           @Override
           protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
               return null;    //这里先暂时返回null
           }
       }
      
    2. 我们知道需要将对象注入到使用者之中,要通过Component,那我们先创建MainComponent,使用@SubComponent注解(为什么是使用SubComponent呢??)

       @Subcomponent
       public interface MainComponent extends AndroidInjector<MainActivity> {
       
           @Subcomponent.Builder
           abstract class Builder extends AndroidInjector.Builder<MainActivity>{}
       
       }
      

      这段代码是模板代码,只需要修改AndroidInjector<T>中的泛型,改成需要注入的对象,也就是MainActivity

    3. 有了MainComponet,就需要将其注入到MainActivity之中

      2.10之前,是通过这行代码DaggerMainComponet.builder().build().inject(this);实现的。

      现在Dagger2会帮我们自动实现注入,但是需要告诉Dagger2哪些Activity需要被注入。

      新建ActivityBindingModule类:

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

      可以看到,这个module里面依赖了MainComponent,所以MainComponent需要使用@SubComponet注解,注入的代码也是通过MainComponent中的抽象方法 Builder 生成的。

      上面这段代码的作用:生成Map<Activity.class, AndroidInjector.Factory<? extends Activity>>的map,并将MainActivity的注入器放入其中。

    4. 创建AppComponent, 在modules中添加 AndroidSupportInjectionModule.class, ActivityBindModule.class,执行make project

       @Component(modules = {AndroidSupportInjectionModule.class, ActivityBindModule.class})
       public interface AppComponent extends AndroidInjector<DemoApp> {
       
           @Component.Builder
           abstract class Builder extends AndroidInjector.Builder<DemoApp>{
       
           }
       }
      
    5. make完成后会生成DaggerAppComponent类,在DemoApp中返回

       @Override
       protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
           return DaggerAppComponent.builder().create(this);
       }       
      
    6. 最后在MainActivity中添加 AndroidInjection.inject(this);

       public class MainActivity extends AppCompatActivity {
       
           @Inject
           Student student;
       
           @Override
           protected void onCreate(Bundle savedInstanceState) {
               super.onCreate(savedInstanceState);
               AndroidInjection.inject(this);
               setContentView(R.layout.activity_main);
               Log.e(TAG, "student ---- " + student.toString());
           }
       }   
      

      这一步也可以通过修改Acitivty的基类,省略

       public class MainActivity extends DaggerActivity{
           ...
       }
       
       //在DaggerActivity的源码中,可以看到内部已经我们添加了这行代码
       @Beta
       public abstract class DaggerActivity extends Activity implements HasFragmentInjector {
       
         @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
       
         @Override
         protected void onCreate(@Nullable Bundle savedInstanceState) {
           AndroidInjection.inject(this);
           super.onCreate(savedInstanceState);
         }
       
         @Override
         public AndroidInjector<Fragment> fragmentInjector() {
           return fragmentInjector;
         }
       }
      

    上面就是完整的注入流程,所有的模板代码Dagger Android都已经帮我们处理好了,我们需要做的只是处理依赖注入关系。

    大致的流程:

    image

    但是这么多步骤,难免会产生错误,而且学习成本也增加了很多,好在Dagger2 2.11之后新增了@ContributesAndroidInjector简化了注入过程(这个后面分析)。

    注解&注入流程分析

    相关文章

      网友评论

        本文标题:Dagger2 Android --- 基础使用篇

        本文链接:https://www.haomeiwen.com/subject/pmjszftx.html