美文网首页
Dagger2基本整体使用讲解--第二章

Dagger2基本整体使用讲解--第二章

作者: 沪漂意哥哥 | 来源:发表于2022-05-26 22:03 被阅读0次

    首先看一张图

    image.png

    举个例子,比如说我通过@Inject去创建一个对象,而这个对象的不是我们能编写的(例如系统的,jar包提供的),我们就不能用@Inject方式来创建这个对象
    例如:

    @Inject
    public TextView textView;
    

    TextView是android库中的,我们没办法用@Inject去注解构造方法,这下改怎么办呢?

    上面图就是解决这个的办法

    下面解释下:

    • Compenent第一章节的时候说过,连接器,他是连接Module和Container的桥梁,我第一章节就说了只有在调用了连接器的的方法,这个对象才开始创建

    • Module 提供创建对象的方法

    • Container需要创建对象的,例子中就Activity

    解决上面的问题

    • 创建Module(供给类,告诉创建TextView,怎么创建)
    //提供对象的Module
    @Module
    public class TestModule {
    
       //为啥需要这个呢,因为provideTextView需要Context做行参,我们当然也要提供一个获取Context的方法啊
       @Provides
       public Context provideContext(){
           //这是一个全局的Application
           Log.d("wyz","执行了:provideContext()");
           return App.application;
       }
    
       //必须使用 @Provides 告诉Compenent 这是一个供给方法 这里我要提供一个TextView
       @Provides
       public TextView provideTextView(Context context){
           // 这里需要一个上下文,我先写null,后期提供方案
           TextView textVie=new TextView(context);
           Log.d("wyz","执行了:provideTextView()创建TextView:"+textVie.hashCode());
    
           return textVie;
       }
    } 
    
    • 创建连接器
    //告诉Component的modules,可以看出是一个数组,所以可以提取多个
    //    重要的事情说三遍 接口 接口 接口
    @Component(modules = {TestModule.class})
    public interface TestCompenent {
       void inject(MainActivity mainActivity);//提供链接方法
    } 
    
    • Build下,生成那个连接器的类,编写MainActivity
    public class MainActivity extends AppCompatActivity {
    
       @Inject
       public TextView textView;
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           DaggerTestCompenent.create().inject(this);
           textView.setText("Dagger2");
           log("大吉大利,我没崩溃textView:"+textView.hashCode());
       }
    
       public void log(String value){
           Log.d("wyz", value);
       }
    } 
    

    运行结果

    04-18 18:13:24.247 31407-31407/com.example.wenyingzhi.myapplication D/wyz: 执行了:provideContext()
    04-18 18:13:24.252 31407-31407/com.example.wenyingzhi.myapplication D/wyz: 执行了:provideTextView()创建TextView:213786299
    04-18 18:13:24.252 31407-31407/com.example.wenyingzhi.myapplication D/wyz: 大吉大利,我没崩溃textView:213786299
    

    注意到了吗?2个TextView的HashCode是一样哦,所以是一个对象

    分析过程

    • 当我们调用DaggerTestCompenent.create().inject(this);连接器的方法后

    • 会看当前类需要@Inject注解的对象,寻找构造方法,有没有通过@Inject注解,发现没有

    • 去Compenent关联的Modules中找@Provides注解的方法,并且是返回TextView的方法,看方法参数需要Context

    • 再去Compenent关联的Modules中找@Provides注解的方法,并且是返回Context的方法

    • 然后按个调用,就完成了一个对象的初始化操作,总之就是你要初始化对象关联的对象,参数都必须能找到,2种方式Module中找到或者类的本身使用了@Inject

    下面来个整体的demo

    public class Teacher {
       public Student student;
       public StudentClass studentClass;
    
       @Inject
       public Teacher(Student student, StudentClass studentClass) {
           this.student = student;
           this.studentClass = studentClass;
       }
    } 
    
    @Module
    public class TeacherModule {
       @Provides
       public Student provideStudent(){
           return new Student();
       }
    
       @Provides
       public StudentClass provideStudentClass(){
           return new StudentClass();
       }
    } 
    
    @Component(modules = {TeacherModule.class})
    public interface TeacherCompenent {
       void inject(MainActivity mainActivity);
    }
    

    因为Teacher的构造方法我通过了@Inject注解所以,不需要再Module处定义@Provide,同理如果我的Student或StudentClass类的构造方法也@Inject注解了,Module中也不需要提供@Provide

    public class Student {
       @Inject
       public Student() {
       }
    }
    

    那么Module中就不再需要定义 provideStudent()方法

    @Module
    public class TeacherModule {
    
       @Provides
       public StudentClass provideStudentClass(){
           return new StudentClass();
       }
    } 
    

    相关文章

      网友评论

          本文标题:Dagger2基本整体使用讲解--第二章

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