本文主要是介绍Dagger2 再菜鸟入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
想放两个链接,是我最初对dagger2的理解,也许对你有帮助:
一些关于dagger2的理解(一) 一些关于dagger2的理解(二)
刚刚开始接触Dagger2的时候,肯定是一脸蒙圈,尤其是对于那些不熟悉注解的程序员来说,更是感觉像天书一般“迷人”。
Dagger2最初给人的印象是很华丽的:尤其是在初级的示例中,一组provide 、Module、Component提供的仅仅是一个无参实体类的初始化,好大一头奶牛只挤出一滴优酸乳。
我个人理解它是这样的:
本质:注解框架;
目的:全新的实例初始化方式(体系);
优势:统一配置,方便复用(但要注意单例等);
劣势:小项目不是很实用
先说优势:
假如你买矿泉水,现在的国家标准是满足一条标准的就允许出售(具体最多几条,谁知道),矿泉水是这样的:
public class KuangquanWater {private String norm;public KuangquanWater(String norm) {this.norm = norm;}public String show(){return norm;}
}
普通情况下是这样的:
public class Consume {KuangquanWater m = new KuangquanWater("透明度");
}
Dagger2是这样的:
@Module
public class WaterModule{public KuangquanWater getWaterOne(){return new KuangquanWater("透明度");}
}
@Component(modules = WaterModule.class)
public interface WaterComponent{void inject(Consume c);
}public class Consume {@InjectKuangquanWater m; void onCreate(){DaggerWaterComponent.builder().build().inject(this);}}
握了颗草,一个初始化搞了这么多幺蛾子,要折寿啊!
如果有一百个人要买这种水,需要一百个Component去包装水。那么这个时候问题来了:如果我标准变了,要求水质必须有两个标准符合,成了这样:
public class KuangquanWater {private String norm1;private String norm2;public KuangquanWater(String norm1,String norm2) {this.norm1 = norm1;this.norm2 = norm2;}public String show(){return norm1+"+"+norm2;}
}
按照普通情况,如果有100个实例化,我要改100个实例化的地方,想想就 法克(汉语发音) 了!
而dagger只需要这样:
@Module
public class WaterModule{public KuangquanWater getWaterOne(){return new KuangquanWater("透明度","矿物质含量");}
}
只修改一个地方,1000个都可以不用管了。
就问你怕不怕!当然实际应用数量不可能这么夸张,但是构造方法的复杂度会增加,也不是这里这么简单了。意义依旧重大的不要不要的。
Dagger2的注解:
@Provide(用于注解方法) 标注某个返回类型的get方法,声明该类型可用并在后面会被用到;
@Module(用于注解类) 用来包含@Provide提供的类型,起到一个包装的作用;
@Component(用于注解类) 把@Module的包装集合起来,供某个类使用;
@Inject(用于注解变量) 在集合中所有包含的@Provide进来的找相同类型;
我还是喜欢打个粗俗的比喻,饿了想吃包子,点个外卖吧:想吃什么馅(@Inject)自己是知道的。而包子店里的馅(@Provider)是要放进包子(@Module)的,包子是怎么到手里的?快递(Build得到的DaggerXXComponent)把各种包子的包裹(@Component)送过来的。如果你想吃好几种口味好几种馅(多个@Inject),可能就需要买多个包子(@Component=(modules={aModule.class,bModule.class…}))了;
来,咱么走一趟,边写边说。
打算做这么个小项目:计算两个人的缘分值。
要用到的算法就是:两个名字的hashCode按比例相加,然后模100,就是圆粪值。
1. 先新建个项目,名字随便起
2. Project的build.gradle添加如下:
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
3. 在module的build.gradle添加如下两处:
apply plugin: 'com.neenbedankt.android-apt'compile 'com.google.dagger:dagger:2.5'
apt 'com.google.dagger:dagger-compiler:2.5'
provided 'org.glassfish:javax.annotation:10.0-b28'
4. 准备三个实体类:
public class People {private int ratio;//计算比例public People(int ratio) {this.ratio = ratio;}public int getScore(String name){return name.hashCode()*ratio/10;}
}public class Man extends People{public Man(int rote) {super(rote);}public Man(){this(6);}
}public class Woman extends People {public Woman(int rote) {super(rote);}public Woman(){this(4);}
}
接下来是重点了
5. 做馅,包包子(@Provide和@Module)
/*** Created by ShuaiZhang on 2016/9/29.*/
@Module
public class PeopleModule {@ProvidesWoman getWoman(){return new Woman(8);//自由指定}@ProvidesMan getMan(){return new Man(8);//自由指定}@Provides @Named("nv")// 存在同样的两个People,就需要@Named来区分People getNv(){return new Woman();}@Provides @Named("nan")People getNan(){return new Man();}
}
其实分开两个来比较好,但是我懒……
6. 打包上面的包子
@Component(modules = PeopleModule.class)//没错,我就是打包
public interface PeopleComponent {void inject(MainActivity m);//指定客户
}
菜单栏BuildàRebuild Project一下。
7. 干掉到手的包子
先上布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.shazeys.yinyuan.MainActivity"><TextViewandroid:layout_marginTop="15dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="男名:" /><EditTextandroid:id="@+id/edt_man"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="女名:" /><EditTextandroid:id="@+id/edt_woman"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextViewandroid:id="@+id/txt_score"android:layout_marginTop="20dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="得分:无" /><Buttonandroid:id="@+id/btn_compute"android:text="计算"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.class:
public class MainActivity extends AppCompatActivity {@InjectWoman woman;@InjectMan man;EditText edtNan;EditText edtNv;TextView txtScore;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);DaggerPeopleComponent.builder()//接收到外卖了.build().inject(this);edtNan = (EditText) findViewById(R.id.edt_man);edtNv = (EditText) findViewById(R.id.edt_woman);txtScore = (TextView) findViewById(R.id.txt_score);Button btnCompute = (Button) findViewById(R.id.btn_compute);btnCompute.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (checkInput())compute();}});}/*** 计算得分并显示*/private void compute() {int nan = man.getScore(edtNan.getText().toString());int nv = woman.getScore(edtNv.getText().toString());int result = (nan+nv)%100;txtScore.setText("得分:"+result);}/*** 判断输入值* @return*/boolean checkInput(){if (edtNan.getText().toString().equals("")){showToast("请输入男名");return false;}if (edtNv.getText().toString().equals("")){showToast("请输入女名");return false;}return true;}void showToast(String tip){Toast.makeText(this,tip,Toast.LENGTH_SHORT).show();}
}
到这里就可以运行看效果了。
不过,最好还是把包子里刚刚留的坑也处理一下,修改MainActivity.class的代码(只显示修改部分,其他均不变):
用@Named来区分相同的@Provide。
赶时髦,代码放到了我的Github上:地址链接
最后声明:本计算不含任何科学或者迷信依据,请勿相信,请勿较真。
这篇关于Dagger2 再菜鸟入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!