首先看一张图
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();
}
}
网友评论