dagger2 解耦 依赖 注入。
懵逼,懵逼。。。
下面总结下我查看网上资料 看得脑浆炸裂 !!的一点小成果
AS导入的流程
1、Modules 下build.gradle
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:24.2.1' testCompile 'junit:junit:4.12' // dagger 2 的配置 compile 'com.google.dagger:dagger:2.4' apt 'com.google.dagger:dagger-compiler:2.4' compile 'org.glassfish:javax.annotation:10.0-b28'// 添加java 注解库 }
apply plugin: 'com.android.application' // 应用插件 apply plugin: 'com.neenbedankt.android-apt'
2、Project中的build.gradle
dependencies { classpath 'com.android.tools.build:gradle:2.2.3' //追加 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
Ok,下面开始进入正式的代码
逆向流程可能更容易理解一点,那先上实体类
1、实体类
public class User {
public String userName;
public User() {
}
@Inject
public User(String userName) {
this.userName = userName;
}
public String getUserName() {
if(null == userName || TextUtils.isEmpty(userName)){
return "空";
}
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String isNew(){
return "这么简单?";
}
}
很平常的一个实体类 但是多了@Inject 属性。
@Inject 用于标记需要注入的依赖,或者标记用于提供依赖的方法
注意!!在实体类中 只有一个构造方法可以用这个属性。
2、@Module层
/*@Module 需要和@Provide是需要一起使用的时候才具有作用的,并且@Component也需要指定了该Module的时候。
*@Module 是告诉Component,可以从这里获取依赖对象。Component就会去找被@Provide标注的方法,相当于构造器的@Inject,可以提供依赖。
*@Component 可以指定多个@Module的,如果需要提供多个依赖的话
*@Component 也可以依赖其它Component存在
*/
@Module //提供依赖对象的实例
public class MyDemo {
/***
* 会根据MainActivit中的
* @Inject
* User user;
* 去自动识别 返回User的 @Provides 方法
*/
// 关键字,标明该方法提供依赖对象
@Provides
User providerUser(){
return new User("lahm");
}
}
@Module 提供依赖对象的实列
@Provides 标明该方法提供依赖对象
一般@Module会结合@Provides使用
3、@Component
/** 作为桥梁,沟通调用者和依赖对象库 类似于中转站 关键字@Component
*@Component可以指定多个@Module的,如果需要提供多个依赖的话
*@Component也可以依赖其它Component存在
*/
@Component (modules = {MyDemo.class})
public interface FistDagger {
//定义注入的方法 注意形参 必须为指定调用的 class 如填写Activity将无法运行
void inject(MainActivity activity);
}
代码这是指定了一个Module的 指定多个Module等下会讲解到
4、调用层,这里用的是MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Inject
User user;
private Button daggerButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 这个类是重新编译后Dagger2自动生成的,所以写这行代码之前要先编译一次
// Build --> Rebuild Project
DaggerFistDagger.create().inject(this);
daggerButton = (Button) findViewById(R.id.button);
daggerButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String showMsg = user.isNew();
String showMsgTwo = user.getUserName();
Toast.makeText(MainActivity.this,showMsg + ";" + showMsgTwo,Toast.LENGTH_LONG).show();
}
}
User对象我们需要实列话 所以也需要增加@Inject字段
重点代码是DaggerFistDagger.create().inject(this)
这个是Build之后自动生成的 它的命名发现了没 就是Dagger+我门定义的接口名称 看下源码 是自动生成Dagger+接口名的 类 会implements我们定义的接口
OK,到这里第一个简单的使用就完成了。
看完上面的列子 可能你会怀疑说 我只想在活动中实现 new User("xxx")的效果,形参俺想传啥就传啥。
好的 那我们只要改下Module
@Module层
@Module
public class MyDemoTwo {
String userNmae;
public MyDemoTwo(String userName) {
this.userNmae= userNmae;
}
@MyInstance
@Provides
User providerUser(){
return new User(msg);
}
}
在moudle这里 你想定义多少个参数都行 注意改了此处class的名称 那么
@Component (modules = {MyDemo.class})
@Component (modules = {MyDemo.class,MyDemoTwo.class})
然后就是该怎么调用了 回到anticity中 调用的代码
// 这个类是重新编译后Dagger2自动生成的,所以写这行代码之前要先编译一次
// Build --> Rebuild Project
DaggerFistDagger.create().inject(this);
这样形参该怎么传呢? 其实还有种写法
DaggerFistDagger.builder().myDemoTwo(new MyDemoTwo("传递的参数")).build().inject(this);
这2种写法 在我的活动中是不能同时兼容的 不清楚原理
看完上面传递参数的写法,你可能会吐槽 这是解耦? 感觉如果改动user实体类 那这里对比以前的直接new 貌似还需要多改动个地方?
这里我脑子里面有些模糊凌乱的模块,但是具体什么又说不清楚。
哎,其实主要是为了装逼啊 有没有。
开个玩笑。就如网上所说 不熟悉MVP架构及DAGGER2+Rxjava+Retrofit2.0模式整合,就没有踏入安卓新时代的门槛。
dagger2是个漫长的学习过程,落后了很多,要开启我的洪荒之力了