zoukankan      html  css  js  c++  java
  • Android依赖注入框架之Dagger2


    主页: https://github.com/google/dagger


    历史
    * Dagger1是由Square公司受到Guice(https://github.com/google/guice)启发创建的依赖注入框架.
    * Dagger2是Dagger1(https://github.com/square/dagger)的分支,由谷歌开发.该项目受到了Auto项目(https://github.com/google/auto)的启发


    优点
    * 没有使用反射,图的验证、配置和预先设置都在编译的时候执行
    * 容易调试,完全具体地调用提供和创建的堆栈
    * 更高的性能,谷歌声称他们提高了13%的处理性能
    * 代码混淆,使用派遣方法,就如同自己写的代码一样


    配置:

    dependencies {
       
        api 'com.google.dagger:dagger:2.15'
        annotationProcessor 'com.google.dagger:dagger-compiler:2.15'
    }

    核心注解:

    @Inject:
      有两个作用:
        1是在需要依赖的类(目标类,即宿主)中标记成员变量告诉Dagger这个类型的变量需要一个实例对象。
        2是标记类中的构造方法(一般为无参构造方法)告诉Dagger我可以提供这种类型的依赖实例。
    @Provides:
      用来提供依赖实例,对方法进行注解,且都是有返回类型的。用来告诉Dagger我们想如何创建并提供该类型的依赖实例(一般会在方法中new出实例)。用@Provides标记的方法,谷歌推荐采用provide为前缀,必须用@Module注解的类中,方法所需的参数也需要以方法的形式返回提供。
    @Module:
      用来标记类(一般类名以Module结尾)。Module主要的作用是用来集中管理@Provides标记的方法。我们定义一个被@Module注解的类,Dagger就会知道在哪里找到依赖来满足创建类的实例。modules的一个重要特征是被设计成区块并可以组合在一起供@Component所注解的类使用。
    @Component:
      用来标记接口或者抽象类(一般以Component结尾),是@Inject(指第一个作用)和@Module之间的桥梁,主要职责是把二者组合在一起,Module中的实例对象必须在Component中暴露出来才能供之后使用。所有的components都可以通过它的modules知道它所提供的依赖范围。一个Component可以依赖一个或多个Component,并拿到被依赖Component暴露出来的实例,Component的dependencies属性就是确定依赖关系的实现。
    @Scope:
      作用域,Dagger2通过自定义注解来限定作用域,有一个默认的作用域注解@Singleton,通常在Android中用来标记在App整个生命周期内存活的实例。也可以自定义一个@PerActivity、@PerFragment注解,用来表明实例生命周期与Activity、Fragment一致。我们可以自定义作用域的粒度(比如@PerUser等等)。

    代码如下:

    package com.loaderman.dagger2;
    
    import android.app.Application;
    /*
    
    Provide 如果是单例模式 对应的Compnent 也要是单例模式
    inject(Activity act) 不能放父类
    即使使用了单利模式,在不同的Activity 对象还是不一样的
    依赖component, component之间的Scoped 不能相同
    子类component 依赖父类的component ,子类component的Scoped 要小于父类的Scoped,Singleton的级别是Application
    多个Moudle 之间不能提供相同的对象实例
    Moudle 中使用了自定义的Scoped 那么对应的Compnent 使用同样的Scoped
    
    * */
    public class MyApp extends Application {
        
        private static AppComponent appComponent;
    
        @Override
        public void onCreate() {
            super.onCreate();
            appComponent = DaggerAppComponent.builder().build();
        }
    
        public static AppComponent getAppComponent() {
            return appComponent;
        }
    }
    package com.loaderman.dagger2;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    
    import javax.inject.Scope;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    @Scope
    @Documented
    @Retention(RUNTIME)
    public @interface ActivityScoped {
    }
    package com.loaderman.dagger2;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    //全局单例
    @Singleton
    @Component(modules = AppModule.class)
    public interface AppComponent {
        AppApi getAppApi();
    }
    package com.loaderman.dagger2;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    @Module
    public class AppModule {
    
        @Singleton
        @Provides
        AppApi providerAppApi() {
            return new AppApi();
        }
    }
    package com.loaderman.dagger2;
    
    import dagger.Component;
    
    //第一步 添加@Component
    //第二步 添加module
    //注意:如果 moudule所依赖的Comonent 中有被单例对象,那么Conponnent也必须是单例对象
    //注意:子类component 依赖父类的component ,子类component的Scoped 要小于父类的Scoped,Singleton的级别是Application
    @ActivityScoped
    @Component(modules ={MainModule.class} ,dependencies = AppComponent.class)
    public interface MainComponent {
        //第三步  写一个方法 绑定Activity /Fragment
        void inject(MainActivity activity);
        void inject(TestActivity activity);
    
    }
    package com.loaderman.dagger2;
    
    import javax.inject.Named;
    
    import dagger.Module;
    import dagger.Provides;
    
    // @Named注解 可实例化对象不同
    //第一步 添加@Module 注解
    @Module
    public class MainModule {
        //第二步 使用Provider 注解 实例化对象
        @Provides
        User providerUserA() {
            return new User();
        }
    
        @Named("B")
        @Provides
        User providerUserB() {
            return new User();
        }
    
        //单例模式
        @ActivityScoped
        @Provides
        MainApi providerMainApi() {
            return new MainApi();
        }
    
        @Provides
        TestA providerTestA() {
            return new TestA();
        }
    
    
    }
    package com.loaderman.dagger2;
    
    public class AppApi {
    }
    package com.loaderman.dagger2;
    
    public class MainApi {
       
    
    }
    package com.loaderman.dagger2;
    
    public class TestA {
    }
    package com.loaderman.dagger2;
    
    import javax.inject.Inject;
    
    public class TestB {
        @Inject
        public TestB() {
        }
    }
    package com.loaderman.dagger2;
    
    public class User {
    }
    package com.loaderman.dagger2;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    
    import javax.inject.Inject;
    
    import dagger.Lazy;
    
    
    public class MainActivity extends AppCompatActivity {
        @Inject
        User userA;
        @Inject
        User userB;
        @Inject
        MainApi apiA;
        @Inject
        MainApi apiB;
        @Inject
        AppApi appApiA;
        @Inject
        AppApi appApiB;
        @Inject
        Lazy<TestA> testALazy;//懒加载机
        @Inject
        TestB testB;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainComponent
                    .builder()
                    //这里传入appComponent实例,我们可以通过application获取到
                    .appComponent(MyApp.getAppComponent())
                    .build()
                    .inject(this);
    
            System.out.println("-----------------输出--------------------------");
            System.out.println("userA" + userA);
            System.out.println("userB" + userB);
            System.out.println("userA==userB? :" + (userA == userB));
            //测试单例
            System.out.println("apiA" + apiA);
            System.out.println("apiB" + apiB);
            System.out.println("apiA==apiB?  :" + (apiA == apiB));
            System.out.println("appApiA" + appApiA);
            System.out.println("appApiB" + appApiB);
            System.out.println("appApiA==appApiB?  :" + (appApiA == appApiB));
            System.out.println("testALazy" + testALazy);
            TestA testA = testALazy.get();
            System.out.println("testA" + testA);
            //注解构造函数,创建实例
            System.out.println("testB" + testB);
    
        }
    
        public void go(View view) {
            startActivity(new Intent(this, TestActivity.class));
        }
    }
    package com.loaderman.dagger2;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    
    import javax.inject.Inject;
    
    public class TestActivity extends AppCompatActivity {
        @Inject
        MainApi mainApi;
        @Inject
        AppApi api;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
            DaggerMainComponent.builder()
                    //这里传入appComponent实例,我们可以通过application获取到
                    .appComponent(MyApp.getAppComponent())
                    .build()
                    .inject(this);
            System.out.println("-----------------输出--------------------------");
            System.out.println("mainApi"+mainApi);
            System.out.println("api"+api);
    
    
        }
    }

    日志:

    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: -----------------MainActivity输出--------------------------
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: userAcom.loaderman.dagger2.User@198c9ed7
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: userBcom.loaderman.dagger2.User@2a8f53c4
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: userA==userB? :false
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: apiAcom.loaderman.dagger2.MainApi@182492ad
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: apiBcom.loaderman.dagger2.MainApi@182492ad
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: apiA==apiB?  :true
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: appApiAcom.loaderman.dagger2.AppApi@b1159e2
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: appApiBcom.loaderman.dagger2.AppApi@b1159e2
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: appApiA==appApiB?  :true
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: testALazydagger.internal.DoubleCheck@26925173
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: testAcom.loaderman.dagger2.TestA@330fe830
    12-26 15:16:03.000 15389-15389/com.loaderman.dagger2 I/System.out: testBcom.loaderman.dagger2.TestB@1ba4aca9
    12-26 15:16:29.560 15389-15389/com.loaderman.dagger2 I/System.out: -----------------TestActivity输出--------------------------
    12-26 15:16:29.560 15389-15389/com.loaderman.dagger2 I/System.out: mainApicom.loaderman.dagger2.MainApi@16e6aef2
    12-26 15:16:29.560 15389-15389/com.loaderman.dagger2 I/System.out: apicom.loaderman.dagger2.AppApi@b1159e2
  • 相关阅读:
    PDO 数据访问抽象层
    注册审核、批量删除
    分页查询
    会话用法
    封装成类
    多条件查询(复选框条件)
    IP子网划分
    redhat 用yum安装的apache、mysql一般默认安装在哪个目录下?
    nslookup
    linux 设置时间
  • 原文地址:https://www.cnblogs.com/loaderman/p/6472276.html
Copyright © 2011-2022 走看看