美文网首页我爱编程
Dagger2的理解和使用

Dagger2的理解和使用

作者: channelRead0 | 来源:发表于2018-06-20 17:04 被阅读0次

    Android:dagger2让你爱不释手-基础依赖注入框架篇
    Android:dagger2让你爱不释手-重点概念讲解、融合篇
    Android:dagger2让你爱不释手-终结篇

    Dagger 2 完全解析(一),Dagger 2 的基本使用与原理
    Dagger 2 完全解析(二),进阶使用 Lazy、Qualifier、Scope 等
    Dagger 2 完全解析(三),Component 的组织关系与 SubComponent
    Dagger 2 完全解析(四),Android 中使用 Dagger 2
    Dagger 2 完全解析(五),Kotlin 中使用 Dagger 2
    Dagger 2 完全解析(六),dagger.android 扩展库的使用

    1、Component的使用

    作为桥连接依赖和被依赖对象。
    每一个Component都会创建一个对应的DaggerComponent
    @Inject注解的构造函数会创建对应类的Factory,用于实例化该类

    /**
     * 药物
     */
    
    public class Medicine {
    
        @Inject
        public Medicine() {
        }
    
        public void treat() {
            LogUtil.e("开始治疗");
        }
    }
    
    /**
     * 注射器
     */
    
    @Component
    public interface Injector {
        //注射动作,指定病患
        void inject(MainActivity mainActivity);
    }
    
    /**
     * 病患
     */
    public class MainActivity extends AppCompatActivity {
    
        @Inject
        Medicine mMedicine;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //口服
            Medicine medicine = new Medicine();
            medicine.treat();
            //打针
            DaggerInjector.create().inject(this);
            mMedicine.treat();
        }
    }  
    

    2、Module使用场景

    1、没有构造函数
    2、有参构造
    3、三方库的类
    每一个@Provides注解的方法都会创建一个Factory用来提供实例化对象给DaggerComponent使用。
    @Provides注解的方法所需要的参数会优先从Module的其他provide中取。

    @Module
    public class ModuleClass {
    
        @Provides
        Gson provideGson() {
            return new Gson();
        }
    }
    
    @Component(modules = ModuleClass.class)
    public interface ComponentClass {
        void inject(MainActivity2 mainActivity);
    }
    
    public class MainActivity2 extends AppCompatActivity {
    
        @Inject
        Gson mGson;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            DaggerComponentClass.create().inject(this);
            String s = mGson.toJson(new Medicine());
            LogUtil.e(s);
        }
    }
    

    3、@Scope作用域

    @Scope是一个元注解,用于注解自定义注解,可以确定注入的实例的生命周期,并在声明周期内保持实例唯一。使用时Module 中 provide 方法中的 Scope 注解必须和 与之绑定的 Component 的 Scope 注解必须一样,否则作用域不同会导致编译时会报错。
    作用域的原理,其实是让生成的依赖实例的生命周期与 Component 绑定,Scope 注解并不能保证生命周期,要想保证赖实例的生命周期,需要确保 Component 的生命周期。

    @Singleton是通过@Scope定义的一个新的注解,能够使同一个Component中的对象保持唯一,保持唯一的条件是通过@Scope标记的注解相同。

    @Singleton并没有创建单例的能力,起作用为
    1、保证Component和Module是匹配的。
    2、代码可读性。

    以页面划分component,一个页面一个component,但这并不是一定的,有时候多页面会共用一个component,因为它们需要的参数一致。

    一个全局component用来管理管理整个App的全局类实例。

    @Scope //注明是Scope 
    @Documented  //标记在文档 
    @Retention(RUNTIME)  // 运行时级别
    public @interface Singleton {}
    
    @Module
    public class FactoryModule {
    
        @Provides
        Gson provideGson() {
            LogUtil.e("创建Gson对象");
            return new Gson();
        }
    
    }
    
    @Component(modules = FactoryModule.class)
    public interface BridgeComponent {
        Gson getGson();
    }
    
    public class App extends Application {
    
        public static BridgeComponent sBridgeComponent;
    
        @Override
        public void onCreate() {
            super.onCreate();
            sBridgeComponent = DaggerBridgeComponent.create();
        }
    
    }
    
    @Module
    public class ActivityModule {
    
        @Singleton
        @Provides
        Person5 providesPersonWithString() {
            return new Person5("xls");
        }
    
    }
    
    @Singleton
    @Component(dependencies = BridgeComponent.class, modules = ActivityModule.class)
    public interface ActivityComponent {
        void inject(MainActivity3 mainActivity);
    }
    
    public class MainActivity3 extends AppCompatActivity {
    
        @Inject
        Person5 mPerson5;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            DaggerActivityComponent.builder().bridgeComponent(App.sBridgeComponent).activityModule(new ActivityModule()).build().inject(this);
            Gson gson = App.sBridgeComponent.getGson();
            LogUtil.e(gson.toJson(mPerson5));
        }
    }
    

    4、有参构造

    MainModule -->providesPerson()中new Person(context)不能直接使用this.context,Module中查找返回Context的方法,并注入。此场景默认调用providesContext方法获取context。

    public class Person {
    
        public String name = "张三";
        public int age = 23;
    
        private Context context;
    
        public Person(Context context) {
            LogUtil.e("a person created with context:" + context);
        }
    }
    
    @Module
    public class MainModule {
    
        private Context context;
    
        public MainModule(Context context) {
            this.context = context;
        }
    
        @Provides
        public Context providesContext() {
            return this.context;
        }
    
        @Provides
        public Person providesPerson(Context context) {
            LogUtil.e("person from module");
            return new Person(context);
        }
    }
    
    @Component(modules = MainModule.class)
    public interface MainComponent {
        void inject(MainActivity4 mainActivity4);
    }
    
    public class MainActivity4 extends AppCompatActivity {
    
        @Inject
        Person mPerson;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainComponent.builder().mainModule(new MainModule(getApplicationContext())).build().inject(this);
            String s = App.getInstance().mGson.toJson(mPerson);
            LogUtil.e(s);
        }
    }
    

    5、自定义标记、限定符

    用于区分同类的不同依赖

    public class Person5 {
    
        public String name = "张三";
        public int age = 23;
        public Context context;
    
        public Person5(Context context) {
            this.context = context;
            LogUtil.e("a person created with context:" + context);
        }
    
        public Person5(String name) {
            this.name = name;
            LogUtil.e("a person created with name:" + name);
        }
    }
    
    @Module
    public class MainModule5 {
        private Context context;
    
        public MainModule5(Context context) {
            this.context = context;
        }
    
        @Provides
        public Context providesContext() {
            return this.context;
        }
    
        //    @Named("context")
        @PersonForContext
        @Provides
        public Person5 providesPersonWithContext(Context context) {
            return new Person5(context);
        }
    
        //    @Named("string")
        @PersonForName
        @Provides
        public Person5 providesPersonWithName() {
            return new Person5("yxm");
        }
    
    }
    
    @Component(modules = MainModule5.class)
    public interface MainComponent5 {
        void inject(MainActivity5 mainActivity5);
    }
    
    public class MainActivity5 extends AppCompatActivity {
    
        //    @Named("string")
        @PersonForName
        @Inject
        Person5 p1;
    
        //    @Named("context")
        @PersonForContext
        @Inject
        Person5 p2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainComponent5.builder().mainModule5(new MainModule5(getApplicationContext())).build().inject(this);
            String s1 = App.getInstance().mGson.toJson(p1);
            LogUtil.e(s1);
            //java.lang.SecurityException: Can not make a java.lang.reflect.Method constructor accessible
    //        String s2 = App.getInstance().mGson.toJson(p2);
    //        LogUtil.e(s2);
        }
    }
    
    @Qualifier  // 关键词
    @Retention(RetentionPolicy.RUNTIME)  // 运行时仍可用
    public @interface PersonForContext {
        // Context 对象的注解
    }
    
    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PersonForName {
        // name 对象的注解
    }
    

    6、Provider、Lazy

    沿用demo5部分文件

    @Module
    public class MainModule5 {
        private Context context;
    
        public MainModule5(Context context) {
            this.context = context;
        }
    
        @Provides
        public Context providesContext() {
            return this.context;
        }
    
        //    @Named("context")
        @PersonForContext
        @Provides
        public Person5 providesPersonWithContext(Context context) {
            return new Person5(context);
        }
    
        //    @Named("string")
        @PersonForName
        @Singleton
        @Provides
        public Person5 providesPersonWithName() {
            return new Person5("yxm");
        }
    
    }
    
    @Singleton
    @Component(modules = MainModule5.class)
    public interface MainComponent5 {
        void inject(MainActivity5 mainActivity5);
    }
    
    
    public class MainActivity5 extends AppCompatActivity {
    
        //    @Named("string")
        @PersonForName
        @Inject
        Person5 p1;
    
        @PersonForName
        @Inject
        Provider<Person5> providerPerson;
    
        //    @Named("context")
        @PersonForContext
        @Inject
        Lazy<Person5> lazyPerson;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainComponent5.builder().mainModule5(new MainModule5(getApplicationContext())).build().inject(this);
            Person5 person5 = lazyPerson.get();// 调用该方法时才会去创建Person,以后每次调用获取的是同一个对象
            Person5 person6 = lazyPerson.get();
            Person5 person7 = providerPerson.get();// 调用该方法时才回去创建Person1,以后每次调用都会重新加载Module中的具体方法,根据Module中的实现,可能相同,可能不相同。加@Singletom注解,创建一次
            Person5 person8 = providerPerson.get();
    
            String s1 = App.getInstance().mGson.toJson(p1);
            LogUtil.e(s1);
            //java.lang.SecurityException: Can not make a java.lang.reflect.Method constructor accessible
    //        String s2 = App.getInstance().mGson.toJson(p2);
    //        LogUtil.e(s2);
        }
    }
    

    总结

    1、将实例化操作抽离出来,达到解耦的效果
    2、单例无需考虑线程是否安全

    相关文章

      网友评论

        本文标题:Dagger2的理解和使用

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