首先看一张图
第一看这个图我也懵逼了,这是啥呀,这相当Dagger2的整体吧
举个例子,比如说我通过@Inject去创建一个对象,而这个对象的不是我们能编写的(例如系统的,jar包提供的),我们就不能用@Inject方式来创建这个对象
例如
@Inject public TextView textView;
TextView是android库中的,我们没办法用@Inject去注解构造方法,这下改怎么办呢?
上面图就是解决这个的办法
下面解释下:
1:Compenent第一章节的时候说过,连接器,他是连接Module和Container的桥梁,我第一章节就说了只有在调用了连接器的的方法,这个对象才开始创建
2:Module 提供创建对象的方法
3:Container需要创建对象的,例子中就Activity
解决上面的问题
1:创建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; } }
2:创建连接器
//告诉Component的modules,可以看出是一个数组,所以可以提取多个 // 重要的事情说三遍 接口 接口 接口 @Component(modules = {TestModule.class}) public interface TestCompenent { void inject(MainActivity mainActivity);//提供链接方法 }
3:最好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是一样哦,所以是一个对象
分析下过程
1:当我们调用DaggerTestCompenent.create().inject(this);连接器的方法后
2:会看当前类需要@Inject注解的对象,寻找构造方法,有没有通过@Inject注解,发现没有
3:去Compenent关联的Modules中找@Provides注解的方法,并且是返回TextView的方法,看方法参数需要Context
4:再去Compenent关联的Modules中找@Provides注解的方法,并且是返回Context的方法
然后按个调用,就完成了一个对象的初始化操作,总之就是你要初始化对象关联的对象,参数都必须能找到,2种方式Module中找到或者类的本身使用了@Inject
下面来个整体的demo
描述:一个Teacher类,类的构造方法,传入一个Student学生类和StudentClass学生科目类
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(); } }