• 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
    
  • 相关阅读:
    shell 默认变量
    diff 实现
    AWK变量
    docker-bridge network
    docker--linux network namespace
    docker-container 操作
    docker--shell和Exec格式
    docker--build自己的image
    docker--container
    docker--删除container和image
  • 原文地址:https://www.cnblogs.com/pedro-neer/p/5303416.html
Copyright © 2020-2023  润新知