zoukankan      html  css  js  c++  java
  • Dagger2 (一) 入坑篇

    为什么是Dagger2

    为了更好的了解Dagger2,请先阅读RoboGuice篇了解依赖注入。

    官方文档称,依赖注入这种技术已经在存在多年了,为什么Dagger2要造轮子?

    Dagger2是第一个全部使用自动生成代码的框架。

    框架生成的代码就像我们自己手写的,可以轻易进行调试和测试,并且很容易了解其原理。

    一.接入

    Dagger2使用了生成代码的方式,这里需要apt的插件。

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.0.0-beta6'
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        }
    }
    

    而Dagger2的主要包中,方法则特别少,主要是编译时提供。

    dependencies {
        compile 'com.google.dagger:dagger:2.0.2'
        provided 'com.google.dagger:dagger-compiler:2.0.2'
        provided 'org.glassfish:javax.annotation:10.0-b28'
    }
    

    由此,接入框架便成功了。

    二.视图注入

    相对于RoboGuice来讲,Dagger2是不支持视图注入的,所以如果选用Dagger2进行对象注入框架的话,可以考虑Dagger2+ButterKnife的配合使用,Dagger2和ButterKnife都没有使用反射机制并且专注于对象或视图的注入。

    三.对象注入

    Dagger2的对象注入同RoboGuice略有不同,但也是和其他注入框架类似,还是使用之前的例子,下面是一个用来储存用户信息的model。注意Dagger2不会默认使用默认构造方法创建以来,必须手动指定。

    public class UserInfo {
        private String userId;
        private String token;
    
        @Inject
        UserInfo(){
        }
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    
        public boolean isLogin(){
            return !TextUtils.isEmpty(token);
        }
    }
    

    当我直接使用Inject这个UserInfo的对象的时候,框架会为我们默认使用构造方法进行初始化。

    public class MainActivity extends AppCompatActivity {
    
        @Inject
        UserInfo userInfo;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            userInfo.setToken("testToken");
            userInfo.setUserId("123456");
        }
    }
    

    四.Module与Component

    Dagger2相比于RoboGuice更为灵活,其中Module的定义与RoboGuice相同,主要指提供依赖的模块,而Component则是一个新出现的词。

    Component英文原意为组件,但在这里面就是一个注入器,相当于RoboGuice中的RoboInject,是提供依赖及使用依赖之间的桥梁,而Dagger2更为灵活的是,我们可以自定义这个注入器。

    废话不多说,上代码。

    首先我们定义一个Module,与RoboGuice不同的是,我们只需要加入注解即可,不需要继承自Dagger2的Module类。

    这里我们提供了Application和Context的依赖。

    @Module
    public class ApplicationModule {
    
        private Application application;
    
        public ApplicationModule(Application application) {
            this.application = application;
        }
    
        @Singleton
        @Provides
        public Application application() {
            return application;
        }
    
        @Singleton
        @Provides
        public Context context() {
            return application;
        }
    }
    

    接下来定义另一个Module,GsonModule。

    还是熟悉的标有需要serializeNulls的Gson对象。

    @Module
    public class GsonModule {
    
        @Provides
        public Gson provideGson() {
            return new GsonBuilder().
                    serializeNulls().
                    create();
        }
    }
    

    接下来我们定义一个注入器,ApplicationComponent。

    定义方法也很简单,注解标有Component,并且可以指定注入器可以注入的模块。

    其中inject方法稍后讲解。

    @Component(modules = {ApplicationModule.class, GsonModule.class})
    public interface ApplicationComponent {
        void inject(MainActivity activity);
    }
    

    好了,写到这,可以放心大胆的编译一下项目了,这时Dagger2会自动生成一些代码,生成的代码是Component前加上Dagger的类,上面的例子生成的就是DaggerApplicationComponent。

    如何使用注入呢?我们用以下方法初始化这个注入器ApplicationComponent。

    public class DaggerApplication extends Application {
    
        private static ApplicationComponent component;
    
        @Override
        public void onCreate() {
            super.onCreate();
            component = DaggerApplicationComponent.builder().
                    applicationModule(new ApplicationModule(this)).
                    gsonModule(new GsonModule()).
                    build();
        }
    
        public static ApplicationComponent Component() {
            return component;
        }
    }
    

    这里只相当于注入器的初始化,并没有真正的注入对象,下面我们在MainActivity中注入对象。

    public class MainActivity extends AppCompatActivity {
    
        @Inject
        Context context;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            component().inject(this);
            Log.e(TAG, "onCreate: " + context.getPackageName());
        }
    
        public ApplicationComponent component() {
            return DaggerApplication.Component();
        }
    }
    

    运行一下,可以看到打印出了日志,至此,我们第一个较为复杂的注入就完成了。这里注入的其实是Application的Context,并不是Activity的Context,为什么呢,以为我们在Application的Module中定义了Context的Provider。

    03-20 22:51:25.046 32476-32476/github.pedroneer.dagger2 E/MainActivity: onCreate: github.pedroneer.dagger2
    
  • 相关阅读:
    LeetCode 32. 最长有效括号(Longest Valid Parentheses)
    LeetCode 141. 环形链表(Linked List Cycle)
    LeetCode 160. 相交链表(Intersection of Two Linked Lists)
    LeetCode 112. 路径总和(Path Sum)
    LeetCode 124. 二叉树中的最大路径和(Binary Tree Maximum Path Sum)
    LightGBM新特性总结
    sql service 事务与锁
    C#泛型实例详解
    C# 中的委托和事件(详解)
    C# DateTime日期格式化
  • 原文地址:https://www.cnblogs.com/pedro-neer/p/5303416.html
Copyright © 2011-2022 走看看